From 1ac710e08a86e4723286873db73edb2a6e99f591 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Wed, 7 Oct 2015 14:54:08 +0100 Subject: mfd: da9150: Add support for Fuel-Gauge Signed-off-by: Adam Thomson Signed-off-by: Lee Jones --- drivers/mfd/da9150-core.c | 156 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 149 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index 94b9bbd1a69b..85ca4b5d0678 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -23,6 +23,77 @@ #include #include +/* Raw device access, used for QIF */ +static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count, + u8 *buf) +{ + struct i2c_msg xfer; + int ret; + + /* + * Read is split into two transfers as device expects STOP/START rather + * than repeated start to carry out this kind of access. + */ + + /* Write address */ + xfer.addr = client->addr; + xfer.flags = 0; + xfer.len = 1; + xfer.buf = &addr; + + ret = i2c_transfer(client->adapter, &xfer, 1); + if (ret != 1) { + if (ret < 0) + return ret; + else + return -EIO; + } + + /* Read data */ + xfer.addr = client->addr; + xfer.flags = I2C_M_RD; + xfer.len = count; + xfer.buf = buf; + + ret = i2c_transfer(client->adapter, &xfer, 1); + if (ret == 1) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + +static int da9150_i2c_write_device(struct i2c_client *client, u8 addr, + int count, const u8 *buf) +{ + struct i2c_msg xfer; + u8 *reg_data; + int ret; + + reg_data = kzalloc(1 + count, GFP_KERNEL); + if (!reg_data) + return -ENOMEM; + + reg_data[0] = addr; + memcpy(®_data[1], buf, count); + + /* Write address & data */ + xfer.addr = client->addr; + xfer.flags = 0; + xfer.len = 1 + count; + xfer.buf = reg_data; + + ret = i2c_transfer(client->adapter, &xfer, 1); + kfree(reg_data); + if (ret == 1) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + static bool da9150_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = { .volatile_reg = da9150_volatile_reg, }; +void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf) +{ + int ret; + + ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf); + if (ret < 0) + dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n", + addr, ret); +} +EXPORT_SYMBOL_GPL(da9150_read_qif); + +void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf) +{ + int ret; + + ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf); + if (ret < 0) + dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n", + addr, ret); +} +EXPORT_SYMBOL_GPL(da9150_write_qif); + u8 da9150_reg_read(struct da9150 *da9150, u16 reg) { int val, ret; @@ -297,19 +390,35 @@ static struct resource da9150_charger_resources[] = { }, }; +static struct resource da9150_fg_resources[] = { + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"), +}; + +enum da9150_dev_idx { + DA9150_GPADC_IDX = 0, + DA9150_CHARGER_IDX, + DA9150_FG_IDX, +}; + static struct mfd_cell da9150_devs[] = { - { + [DA9150_GPADC_IDX] = { .name = "da9150-gpadc", .of_compatible = "dlg,da9150-gpadc", .resources = da9150_gpadc_resources, .num_resources = ARRAY_SIZE(da9150_gpadc_resources), }, - { + [DA9150_CHARGER_IDX] = { .name = "da9150-charger", .of_compatible = "dlg,da9150-charger", .resources = da9150_charger_resources, .num_resources = ARRAY_SIZE(da9150_charger_resources), }, + [DA9150_FG_IDX] = { + .name = "da9150-fuel-gauge", + .of_compatible = "dlg,da9150-fuel-gauge", + .resources = da9150_fg_resources, + .num_resources = ARRAY_SIZE(da9150_fg_resources), + }, }; static int da9150_probe(struct i2c_client *client, @@ -317,6 +426,7 @@ static int da9150_probe(struct i2c_client *client, { struct da9150 *da9150; struct da9150_pdata *pdata = dev_get_platdata(&client->dev); + int qif_addr; int ret; da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL); @@ -335,16 +445,41 @@ static int da9150_probe(struct i2c_client *client, return ret; } - da9150->irq_base = pdata ? pdata->irq_base : -1; + /* Setup secondary I2C interface for QIF access */ + qif_addr = da9150_reg_read(da9150, DA9150_CORE2WIRE_CTRL_A); + qif_addr = (qif_addr & DA9150_CORE_BASE_ADDR_MASK) >> 1; + qif_addr |= DA9150_QIF_I2C_ADDR_LSB; + da9150->core_qif = i2c_new_dummy(client->adapter, qif_addr); + if (!da9150->core_qif) { + dev_err(da9150->dev, "Failed to attach QIF client\n"); + return -ENODEV; + } + + i2c_set_clientdata(da9150->core_qif, da9150); + + if (pdata) { + da9150->irq_base = pdata->irq_base; + + da9150_devs[DA9150_FG_IDX].platform_data = pdata->fg_pdata; + da9150_devs[DA9150_FG_IDX].pdata_size = + sizeof(struct da9150_fg_pdata); + } else { + da9150->irq_base = -1; + } ret = regmap_add_irq_chip(da9150->regmap, da9150->irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, da9150->irq_base, &da9150_regmap_irq_chip, &da9150->regmap_irq_data); - if (ret) - return ret; + if (ret) { + dev_err(da9150->dev, "Failed to add regmap irq chip: %d\n", + ret); + goto regmap_irq_fail; + } + da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data); + enable_irq_wake(da9150->irq); ret = mfd_add_devices(da9150->dev, -1, da9150_devs, @@ -352,11 +487,17 @@ static int da9150_probe(struct i2c_client *client, da9150->irq_base, NULL); if (ret) { dev_err(da9150->dev, "Failed to add child devices: %d\n", ret); - regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data); - return ret; + goto mfd_fail; } return 0; + +mfd_fail: + regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data); +regmap_irq_fail: + i2c_unregister_device(da9150->core_qif); + + return ret; } static int da9150_remove(struct i2c_client *client) @@ -365,6 +506,7 @@ static int da9150_remove(struct i2c_client *client) regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data); mfd_remove_devices(da9150->dev); + i2c_unregister_device(da9150->core_qif); return 0; } -- cgit v1.2.3 From a419b4fd9138c6cd5049d14813e7d94e596e4540 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Wed, 7 Oct 2015 14:54:16 +0100 Subject: power: Add support for DA9150 Fuel-Gauge This adds power supply driver support for the Fuel-Gauge part of the DA9150 combined Charger and Fuel-Gauge device. Signed-off-by: Adam Thomson Acked-by: Sebastian Reichel Signed-off-by: Lee Jones --- drivers/power/Kconfig | 10 + drivers/power/Makefile | 1 + drivers/power/da9150-fg.c | 579 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 590 insertions(+) create mode 100644 drivers/power/da9150-fg.c (limited to 'drivers') diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f8758d6febf8..8d53f58f20dd 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -204,6 +204,16 @@ config CHARGER_DA9150 This driver can also be built as a module. If so, the module will be called da9150-charger. +config BATTERY_DA9150 + tristate "Dialog Semiconductor DA9150 Fuel Gauge support" + depends on MFD_DA9150 + help + Say Y here to enable support for the Fuel-Gauge unit of the DA9150 + Integrated Charger & Fuel-Gauge IC + + This driver can also be built as a module. If so, the module will be + called da9150-fg. + config AXP288_CHARGER tristate "X-Powers AXP288 Charger" depends on MFD_AXP20X && EXTCON_AXP288 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 5752ce818f51..cbdf89d595a3 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o +obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o diff --git a/drivers/power/da9150-fg.c b/drivers/power/da9150-fg.c new file mode 100644 index 000000000000..8b8ce978656a --- /dev/null +++ b/drivers/power/da9150-fg.c @@ -0,0 +1,579 @@ +/* + * DA9150 Fuel-Gauge Driver + * + * Copyright (c) 2015 Dialog Semiconductor + * + * Author: Adam Thomson + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Core2Wire */ +#define DA9150_QIF_READ (0x0 << 7) +#define DA9150_QIF_WRITE (0x1 << 7) +#define DA9150_QIF_CODE_MASK 0x7F + +#define DA9150_QIF_BYTE_SIZE 8 +#define DA9150_QIF_BYTE_MASK 0xFF +#define DA9150_QIF_SHORT_SIZE 2 +#define DA9150_QIF_LONG_SIZE 4 + +/* QIF Codes */ +#define DA9150_QIF_UAVG 6 +#define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_IAVG 8 +#define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_NTCAVG 12 +#define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_SHUNT_VAL 36 +#define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SD_GAIN 38 +#define DA9150_QIF_SD_GAIN_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_FCC_MAH 40 +#define DA9150_QIF_FCC_MAH_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SOC_PCT 43 +#define DA9150_QIF_SOC_PCT_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_CHARGE_LIMIT 44 +#define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_DISCHARGE_LIMIT 45 +#define DA9150_QIF_DISCHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_FW_MAIN_VER 118 +#define DA9150_QIF_FW_MAIN_VER_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_E_FG_STATUS 126 +#define DA9150_QIF_E_FG_STATUS_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SYNC 127 +#define DA9150_QIF_SYNC_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_MAX_CODES 128 + +/* QIF Sync Timeout */ +#define DA9150_QIF_SYNC_TIMEOUT 1000 +#define DA9150_QIF_SYNC_RETRIES 10 + +/* QIF E_FG_STATUS */ +#define DA9150_FG_IRQ_LOW_SOC_MASK (1 << 0) +#define DA9150_FG_IRQ_HIGH_SOC_MASK (1 << 1) +#define DA9150_FG_IRQ_SOC_MASK \ + (DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK) + +/* Private data */ +struct da9150_fg { + struct da9150 *da9150; + struct device *dev; + + struct mutex io_lock; + + struct power_supply *battery; + struct delayed_work work; + u32 interval; + + int warn_soc; + int crit_soc; + int soc; +}; + +/* Battery Properties */ +static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size) + +{ + u8 buf[size]; + u8 read_addr; + u32 res = 0; + int i; + + /* Set QIF code (READ mode) */ + read_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_READ; + + da9150_read_qif(fg->da9150, read_addr, size, buf); + for (i = 0; i < size; ++i) + res |= (buf[i] << (i * DA9150_QIF_BYTE_SIZE)); + + return res; +} + +static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size, + u32 val) + +{ + u8 buf[size]; + u8 write_addr; + int i; + + /* Set QIF code (WRITE mode) */ + write_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_WRITE; + + for (i = 0; i < size; ++i) { + buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) & + DA9150_QIF_BYTE_MASK; + } + da9150_write_qif(fg->da9150, write_addr, size, buf); +} + +/* Trigger QIF Sync to update QIF readable data */ +static void da9150_fg_read_sync_start(struct da9150_fg *fg) +{ + int i = 0; + u32 res = 0; + + mutex_lock(&fg->io_lock); + + /* Check if QIF sync already requested, and write to sync if not */ + res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, + DA9150_QIF_SYNC_SIZE); + if (res > 0) + da9150_fg_write_attr(fg, DA9150_QIF_SYNC, + DA9150_QIF_SYNC_SIZE, 0); + + /* Wait for sync to complete */ + res = 0; + while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) { + usleep_range(DA9150_QIF_SYNC_TIMEOUT, + DA9150_QIF_SYNC_TIMEOUT * 2); + res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, + DA9150_QIF_SYNC_SIZE); + } + + /* Check if sync completed */ + if (res == 0) + dev_err(fg->dev, "Failed to perform QIF read sync!\n"); +} + +/* + * Should always be called after QIF sync read has been performed, and all + * attributes required have been accessed. + */ +static inline void da9150_fg_read_sync_end(struct da9150_fg *fg) +{ + mutex_unlock(&fg->io_lock); +} + +/* Sync read of single QIF attribute */ +static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size) +{ + u32 val; + + da9150_fg_read_sync_start(fg); + val = da9150_fg_read_attr(fg, code, size); + da9150_fg_read_sync_end(fg); + + return val; +} + +/* Wait for QIF Sync, write QIF data and wait for ack */ +static void da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size, + u32 val) +{ + int i = 0; + u32 res = 0, sync_val; + + mutex_lock(&fg->io_lock); + + /* Check if QIF sync already requested */ + res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, + DA9150_QIF_SYNC_SIZE); + + /* Wait for an existing sync to complete */ + while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) { + usleep_range(DA9150_QIF_SYNC_TIMEOUT, + DA9150_QIF_SYNC_TIMEOUT * 2); + res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, + DA9150_QIF_SYNC_SIZE); + } + + if (res == 0) { + dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n"); + mutex_unlock(&fg->io_lock); + return; + } + + /* Write value for QIF code */ + da9150_fg_write_attr(fg, code, size, val); + + /* Wait for write acknowledgment */ + i = 0; + sync_val = res; + while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) { + usleep_range(DA9150_QIF_SYNC_TIMEOUT, + DA9150_QIF_SYNC_TIMEOUT * 2); + res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, + DA9150_QIF_SYNC_SIZE); + } + + mutex_unlock(&fg->io_lock); + + /* Check write was actually successful */ + if (res != (sync_val + 1)) + dev_err(fg->dev, "Error performing QIF sync write for code %d\n", + code); +} + +/* Power Supply attributes */ +static int da9150_fg_capacity(struct da9150_fg *fg, + union power_supply_propval *val) +{ + val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT, + DA9150_QIF_SOC_PCT_SIZE); + + if (val->intval > 100) + val->intval = 100; + + return 0; +} + +static int da9150_fg_current_avg(struct da9150_fg *fg, + union power_supply_propval *val) +{ + u32 iavg, sd_gain, shunt_val; + u64 div, res; + + da9150_fg_read_sync_start(fg); + iavg = da9150_fg_read_attr(fg, DA9150_QIF_IAVG, + DA9150_QIF_IAVG_SIZE); + shunt_val = da9150_fg_read_attr(fg, DA9150_QIF_SHUNT_VAL, + DA9150_QIF_SHUNT_VAL_SIZE); + sd_gain = da9150_fg_read_attr(fg, DA9150_QIF_SD_GAIN, + DA9150_QIF_SD_GAIN_SIZE); + da9150_fg_read_sync_end(fg); + + div = (u64) (sd_gain * shunt_val * 65536ULL); + do_div(div, 1000000); + res = (u64) (iavg * 1000000ULL); + do_div(res, div); + + val->intval = (int) res; + + return 0; +} + +static int da9150_fg_voltage_avg(struct da9150_fg *fg, + union power_supply_propval *val) +{ + u64 res; + + val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_UAVG, + DA9150_QIF_UAVG_SIZE); + + res = (u64) (val->intval * 186ULL); + do_div(res, 10000); + val->intval = (int) res; + + return 0; +} + +static int da9150_fg_charge_full(struct da9150_fg *fg, + union power_supply_propval *val) +{ + val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_FCC_MAH, + DA9150_QIF_FCC_MAH_SIZE); + + val->intval = val->intval * 1000; + + return 0; +} + +/* + * Temperature reading from device is only valid if battery/system provides + * valid NTC to associated pin of DA9150 chip. + */ +static int da9150_fg_temp(struct da9150_fg *fg, + union power_supply_propval *val) +{ + val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG, + DA9150_QIF_NTCAVG_SIZE); + + val->intval = (val->intval * 10) / 1048576; + + return 0; +} + +static enum power_supply_property da9150_fg_props[] = { + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_VOLTAGE_AVG, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_TEMP, +}; + +static int da9150_fg_get_prop(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_CAPACITY: + ret = da9150_fg_capacity(fg, val); + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + ret = da9150_fg_current_avg(fg, val); + break; + case POWER_SUPPLY_PROP_VOLTAGE_AVG: + ret = da9150_fg_voltage_avg(fg, val); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + ret = da9150_fg_charge_full(fg, val); + break; + case POWER_SUPPLY_PROP_TEMP: + ret = da9150_fg_temp(fg, val); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/* Repeated SOC check */ +static bool da9150_fg_soc_changed(struct da9150_fg *fg) +{ + union power_supply_propval val; + + da9150_fg_capacity(fg, &val); + if (val.intval != fg->soc) { + fg->soc = val.intval; + return true; + } + + return false; +} + +static void da9150_fg_work(struct work_struct *work) +{ + struct da9150_fg *fg = container_of(work, struct da9150_fg, work.work); + + /* Report if SOC has changed */ + if (da9150_fg_soc_changed(fg)) + power_supply_changed(fg->battery); + + schedule_delayed_work(&fg->work, msecs_to_jiffies(fg->interval)); +} + +/* SOC level event configuration */ +static void da9150_fg_soc_event_config(struct da9150_fg *fg) +{ + int soc; + + soc = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT, + DA9150_QIF_SOC_PCT_SIZE); + + if (soc > fg->warn_soc) { + /* If SOC > warn level, set discharge warn level event */ + da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT, + DA9150_QIF_DISCHARGE_LIMIT_SIZE, + fg->warn_soc + 1); + } else if ((soc <= fg->warn_soc) && (soc > fg->crit_soc)) { + /* + * If SOC <= warn level, set discharge crit level event, + * and set charge warn level event. + */ + da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT, + DA9150_QIF_DISCHARGE_LIMIT_SIZE, + fg->crit_soc + 1); + + da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT, + DA9150_QIF_CHARGE_LIMIT_SIZE, + fg->warn_soc); + } else if (soc <= fg->crit_soc) { + /* If SOC <= crit level, set charge crit level event */ + da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT, + DA9150_QIF_CHARGE_LIMIT_SIZE, + fg->crit_soc); + } +} + +static irqreturn_t da9150_fg_irq(int irq, void *data) +{ + struct da9150_fg *fg = data; + u32 e_fg_status; + + /* Read FG IRQ status info */ + e_fg_status = da9150_fg_read_attr(fg, DA9150_QIF_E_FG_STATUS, + DA9150_QIF_E_FG_STATUS_SIZE); + + /* Handle warning/critical threhold events */ + if (e_fg_status & DA9150_FG_IRQ_SOC_MASK) + da9150_fg_soc_event_config(fg); + + /* Clear any FG IRQs */ + da9150_fg_write_attr(fg, DA9150_QIF_E_FG_STATUS, + DA9150_QIF_E_FG_STATUS_SIZE, e_fg_status); + + return IRQ_HANDLED; +} + +static struct da9150_fg_pdata *da9150_fg_dt_pdata(struct device *dev) +{ + struct device_node *fg_node = dev->of_node; + struct da9150_fg_pdata *pdata; + + pdata = devm_kzalloc(dev, sizeof(struct da9150_fg_pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + of_property_read_u32(fg_node, "dlg,update-interval", + &pdata->update_interval); + of_property_read_u8(fg_node, "dlg,warn-soc-level", + &pdata->warn_soc_lvl); + of_property_read_u8(fg_node, "dlg,crit-soc-level", + &pdata->crit_soc_lvl); + + return pdata; +} + +static const struct power_supply_desc fg_desc = { + .name = "da9150-fg", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = da9150_fg_props, + .num_properties = ARRAY_SIZE(da9150_fg_props), + .get_property = da9150_fg_get_prop, +}; + +static int da9150_fg_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct da9150 *da9150 = dev_get_drvdata(dev->parent); + struct da9150_fg_pdata *fg_pdata = dev_get_platdata(dev); + struct da9150_fg *fg; + int ver, irq, ret = 0; + + fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL); + if (fg == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, fg); + fg->da9150 = da9150; + fg->dev = dev; + + mutex_init(&fg->io_lock); + + /* Enable QIF */ + da9150_set_bits(da9150, DA9150_CORE2WIRE_CTRL_A, DA9150_FG_QIF_EN_MASK, + DA9150_FG_QIF_EN_MASK); + + fg->battery = devm_power_supply_register(dev, &fg_desc, NULL); + if (IS_ERR(fg->battery)) { + ret = PTR_ERR(fg->battery); + return ret; + } + + ver = da9150_fg_read_attr(fg, DA9150_QIF_FW_MAIN_VER, + DA9150_QIF_FW_MAIN_VER_SIZE); + dev_info(dev, "Version: 0x%x\n", ver); + + /* Handle DT data if provided */ + if (dev->of_node) { + fg_pdata = da9150_fg_dt_pdata(dev); + dev->platform_data = fg_pdata; + } + + /* Handle any pdata provided */ + if (fg_pdata) { + fg->interval = fg_pdata->update_interval; + + if (fg_pdata->warn_soc_lvl > 100) + dev_warn(dev, "Invalid SOC warning level provided, Ignoring"); + else + fg->warn_soc = fg_pdata->warn_soc_lvl; + + if ((fg_pdata->crit_soc_lvl > 100) || + (fg_pdata->crit_soc_lvl >= fg_pdata->warn_soc_lvl)) + dev_warn(dev, "Invalid SOC critical level provided, Ignoring"); + else + fg->crit_soc = fg_pdata->crit_soc_lvl; + + + } + + /* Configure initial SOC level events */ + da9150_fg_soc_event_config(fg); + + /* + * If an interval period has been provided then setup repeating + * work for reporting data updates. + */ + if (fg->interval) { + INIT_DELAYED_WORK(&fg->work, da9150_fg_work); + schedule_delayed_work(&fg->work, + msecs_to_jiffies(fg->interval)); + } + + /* Register IRQ */ + irq = platform_get_irq_byname(pdev, "FG"); + if (irq < 0) { + dev_err(dev, "Failed to get IRQ FG: %d\n", irq); + ret = irq; + goto irq_fail; + } + + ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq, + IRQF_ONESHOT, "FG", fg); + if (ret) { + dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret); + goto irq_fail; + } + + return 0; + +irq_fail: + if (fg->interval) + cancel_delayed_work(&fg->work); + + return ret; +} + +static int da9150_fg_remove(struct platform_device *pdev) +{ + struct da9150_fg *fg = platform_get_drvdata(pdev); + + if (fg->interval) + cancel_delayed_work(&fg->work); + + return 0; +} + +static int da9150_fg_resume(struct platform_device *pdev) +{ + struct da9150_fg *fg = platform_get_drvdata(pdev); + + /* + * Trigger SOC check to happen now so as to indicate any value change + * since last check before suspend. + */ + if (fg->interval) + flush_delayed_work(&fg->work); + + return 0; +} + +static struct platform_driver da9150_fg_driver = { + .driver = { + .name = "da9150-fuel-gauge", + }, + .probe = da9150_fg_probe, + .remove = da9150_fg_remove, + .resume = da9150_fg_resume, +}; + +module_platform_driver(da9150_fg_driver); + +MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150"); +MODULE_AUTHOR("Adam Thomson "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1d7f833fd182c989a7f0d2861a68acbee99865cf Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Wed, 7 Oct 2015 14:54:31 +0100 Subject: mfd: da9150: Use DEFINE_RES_IRQ_NAMED() help macro for IRQ resource Suggested-by: Lee Jones Signed-off-by: Adam Thomson Signed-off-by: Lee Jones --- drivers/mfd/da9150-core.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index 85ca4b5d0678..195fdcfa1a0d 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -355,39 +355,14 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = { }; static struct resource da9150_gpadc_resources[] = { - { - .name = "GPADC", - .start = DA9150_IRQ_GPADC, - .end = DA9150_IRQ_GPADC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"), }; static struct resource da9150_charger_resources[] = { - { - .name = "CHG_STATUS", - .start = DA9150_IRQ_CHG, - .end = DA9150_IRQ_CHG, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_TJUNC", - .start = DA9150_IRQ_TJUNC, - .end = DA9150_IRQ_TJUNC, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_VFAULT", - .start = DA9150_IRQ_VFAULT, - .end = DA9150_IRQ_VFAULT, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_VBUS", - .start = DA9150_IRQ_VBUS, - .end = DA9150_IRQ_VBUS, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"), }; static struct resource da9150_fg_resources[] = { -- cgit v1.2.3 From 98a3be44ffa67b812de7aa7aed9f2331edcfb1a5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 23 Oct 2015 12:16:41 +0300 Subject: mfd: core: redo ACPI matching of the children devices There is at least one board on the market, i.e. Intel Galileo Gen2, that uses _ADR to distinguish the devices under one actual device. Due to this we have to improve the quirk in the MFD core to handle that board. Acked-by: Rafael J. Wysocki Acked-by: Lee Jones Signed-off-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- Documentation/acpi/enumeration.txt | 11 +++++--- drivers/mfd/mfd-core.c | 52 ++++++++++++++++++++++++++------------ include/linux/mfd/core.h | 10 ++++++-- 3 files changed, 52 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt index b731b292e812..a91ec5af52df 100644 --- a/Documentation/acpi/enumeration.txt +++ b/Documentation/acpi/enumeration.txt @@ -347,13 +347,18 @@ For the first case, the MFD drivers do not need to do anything. The resulting child platform device will have its ACPI_COMPANION() set to point to the parent device. -If the ACPI namespace has a device that we can match using an ACPI id, -the id should be set like: +If the ACPI namespace has a device that we can match using an ACPI id or ACPI +adr, the cell should be set like: + + static struct mfd_cell_acpi_match my_subdevice_cell_acpi_match = { + .pnpid = "XYZ0001", + .adr = 0, + }; static struct mfd_cell my_subdevice_cell = { .name = "my_subdevice", /* set the resources relative to the parent */ - .acpi_pnpid = "XYZ0001", + .acpi_match = &my_subdevice_cell_acpi_match, }; The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index c17635d3e504..60b60dc63ddd 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -82,29 +82,49 @@ static int mfd_platform_add_cell(struct platform_device *pdev, static void mfd_acpi_add_device(const struct mfd_cell *cell, struct platform_device *pdev) { - struct acpi_device *parent_adev; + const struct mfd_cell_acpi_match *match = cell->acpi_match; + struct acpi_device *parent, *child; struct acpi_device *adev; - parent_adev = ACPI_COMPANION(pdev->dev.parent); - if (!parent_adev) + parent = ACPI_COMPANION(pdev->dev.parent); + if (!parent) return; /* - * MFD child device gets its ACPI handle either from the ACPI - * device directly under the parent that matches the acpi_pnpid or - * it will use the parent handle if is no acpi_pnpid is given. + * MFD child device gets its ACPI handle either from the ACPI device + * directly under the parent that matches the either _HID or _CID, or + * _ADR or it will use the parent handle if is no ID is given. + * + * Note that use of _ADR is a grey area in the ACPI specification, + * though Intel Galileo Gen2 is using it to distinguish the children + * devices. */ - adev = parent_adev; - if (cell->acpi_pnpid) { - struct acpi_device_id ids[2] = {}; - struct acpi_device *child_adev; - - strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id)); - list_for_each_entry(child_adev, &parent_adev->children, node) - if (acpi_match_device_ids(child_adev, ids)) { - adev = child_adev; - break; + adev = parent; + if (match) { + if (match->pnpid) { + struct acpi_device_id ids[2] = {}; + + strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id)); + list_for_each_entry(child, &parent->children, node) { + if (acpi_match_device_ids(child, ids)) { + adev = child; + break; + } + } + } else { + unsigned long long adr; + acpi_status status; + + list_for_each_entry(child, &parent->children, node) { + status = acpi_evaluate_integer(child->handle, + "_ADR", NULL, + &adr); + if (ACPI_SUCCESS(status) && match->adr == adr) { + adev = child; + break; + } } + } } ACPI_COMPANION_SET(&pdev->dev, adev); diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index a76bc100bf97..27dac3ff18b9 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -18,6 +18,12 @@ struct irq_domain; +/* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */ +struct mfd_cell_acpi_match { + const char *pnpid; + const unsigned long long adr; +}; + /* * This struct describes the MFD part ("cell"). * After registration the copy of this structure will become the platform data @@ -44,8 +50,8 @@ struct mfd_cell { */ const char *of_compatible; - /* Matches ACPI PNP id, either _HID or _CID */ - const char *acpi_pnpid; + /* Matches ACPI */ + const struct mfd_cell_acpi_match *acpi_match; /* * These resources can be specified relative to the parent device. -- cgit v1.2.3 From 236fd469f4d1beb59a47875fa3f222d514173ad0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 23 Oct 2015 12:16:42 +0300 Subject: mfd: intel_quark_i2c_gpio: load gpio driver first On Intel Galileo boards the GPIO expander is connected to i2c bus. Moreover it is able to generate interrupt, but interrupt line is connected to GPIO. That's why we have to have GPIO driver in place when we will probe i2c host with device connected to it. Acked-by: Lee Jones Signed-off-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/mfd/intel_quark_i2c_gpio.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 1ce16037d043..958c13473e8c 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -89,13 +89,6 @@ static struct resource intel_quark_gpio_res[] = { }; static struct mfd_cell intel_quark_mfd_cells[] = { - { - .id = MFD_I2C_BAR, - .name = "i2c_designware", - .num_resources = ARRAY_SIZE(intel_quark_i2c_res), - .resources = intel_quark_i2c_res, - .ignore_resource_conflicts = true, - }, { .id = MFD_GPIO_BAR, .name = "gpio-dwapb", @@ -103,6 +96,13 @@ static struct mfd_cell intel_quark_mfd_cells[] = { .resources = intel_quark_gpio_res, .ignore_resource_conflicts = true, }, + { + .id = MFD_I2C_BAR, + .name = "i2c_designware", + .num_resources = ARRAY_SIZE(intel_quark_i2c_res), + .resources = intel_quark_i2c_res, + .ignore_resource_conflicts = true, + }, }; static const struct pci_device_id intel_quark_mfd_ids[] = { @@ -248,12 +248,11 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, dev_set_drvdata(&pdev->dev, quark_mfd); - ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]); + ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); if (ret) return ret; - ret = intel_quark_gpio_setup(pdev, - &intel_quark_mfd_cells[MFD_GPIO_BAR]); + ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); if (ret) return ret; -- cgit v1.2.3 From 918fe70cf4750e21350a8a40b28117b9e2991a10 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 23 Oct 2015 12:16:43 +0300 Subject: mfd: intel_quark_i2c_gpio: support devices behind i2c bus On Intel Galileo Gen2 the GPIO expanders are connected to the i2c bus. For those devices the ACPI table has specific parameters that refer to an actual i2c host controller. Since MFD now copes with that specific configuration we have to provide a necessary information how to distinguish devices in ACPI namespace. Here the _ADR values are provided. Acked-by: Lee Jones Signed-off-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/mfd/intel_quark_i2c_gpio.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 958c13473e8c..042137465300 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -31,6 +31,10 @@ #define MFD_I2C_BAR 0 #define MFD_GPIO_BAR 1 +/* ACPI _ADR value to match the child node */ +#define MFD_ACPI_MATCH_GPIO 0ULL +#define MFD_ACPI_MATCH_I2C 1ULL + /* The base GPIO number under GPIOLIB framework */ #define INTEL_QUARK_MFD_GPIO_BASE 8 @@ -82,16 +86,25 @@ static struct resource intel_quark_i2c_res[] = { }, }; +static struct mfd_cell_acpi_match intel_quark_acpi_match_i2c = { + .adr = MFD_ACPI_MATCH_I2C, +}; + static struct resource intel_quark_gpio_res[] = { [INTEL_QUARK_IORES_MEM] = { .flags = IORESOURCE_MEM, }, }; +static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = { + .adr = MFD_ACPI_MATCH_GPIO, +}; + static struct mfd_cell intel_quark_mfd_cells[] = { { .id = MFD_GPIO_BAR, .name = "gpio-dwapb", + .acpi_match = &intel_quark_acpi_match_gpio, .num_resources = ARRAY_SIZE(intel_quark_gpio_res), .resources = intel_quark_gpio_res, .ignore_resource_conflicts = true, @@ -99,6 +112,7 @@ static struct mfd_cell intel_quark_mfd_cells[] = { { .id = MFD_I2C_BAR, .name = "i2c_designware", + .acpi_match = &intel_quark_acpi_match_i2c, .num_resources = ARRAY_SIZE(intel_quark_i2c_res), .resources = intel_quark_i2c_res, .ignore_resource_conflicts = true, -- cgit v1.2.3 From 40d8edc9bf056ea83e50152a4ccd33048d26ccde Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 23 Oct 2015 12:16:44 +0300 Subject: at24: enable ACPI device found on Galileo Gen2 There is a 24c08 chip connected to i2c bus on Intel Galileo Gen2 board. Enable it via ACPI ID INT3499. Signed-off-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/misc/eeprom/at24.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index c6cb7f8f325e..5d7c0900fa1b 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -131,6 +132,12 @@ static const struct i2c_device_id at24_ids[] = { }; MODULE_DEVICE_TABLE(i2c, at24_ids); +static const struct acpi_device_id at24_acpi_ids[] = { + { "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) }, + { } +}; +MODULE_DEVICE_TABLE(acpi, at24_acpi_ids); + /*-------------------------------------------------------------------------*/ /* @@ -467,21 +474,29 @@ static void at24_get_ofdata(struct i2c_client *client, static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct at24_platform_data chip; + kernel_ulong_t magic = 0; bool writable; int use_smbus = 0; int use_smbus_write = 0; struct at24_data *at24; int err; unsigned i, num_addresses; - kernel_ulong_t magic; if (client->dev.platform_data) { chip = *(struct at24_platform_data *)client->dev.platform_data; } else { - if (!id->driver_data) + if (id) { + magic = id->driver_data; + } else { + const struct acpi_device_id *aid; + + aid = acpi_match_device(at24_acpi_ids, &client->dev); + if (aid) + magic = aid->driver_data; + } + if (!magic) return -ENODEV; - magic = id->driver_data; chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); magic >>= AT24_SIZE_BYTELEN; chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); @@ -661,6 +676,7 @@ static int at24_remove(struct i2c_client *client) static struct i2c_driver at24_driver = { .driver = { .name = "at24", + .acpi_match_table = ACPI_PTR(at24_acpi_ids), }, .probe = at24_probe, .remove = at24_remove, -- cgit v1.2.3 From 385c0012dfa0b1cdcb16907d847eb2a720f17a9a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 25 Aug 2015 07:48:10 +0200 Subject: mfd: cros_ec_i2c: Add OF match table The Documentation/devicetree/bindings/mfd/cros-ec.txt DT binding doc lists "google,cros-ec-i2c" as a compatible string but the corresponding driver does not have an OF match table. Add the table to the driver so the I2C core can do an OF style match. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/cros_ec_i2c.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c index d06e4b46db80..56a466469664 100644 --- a/drivers/mfd/cros_ec_i2c.c +++ b/drivers/mfd/cros_ec_i2c.c @@ -344,6 +344,12 @@ static int cros_ec_i2c_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend, cros_ec_i2c_resume); +static const struct of_device_id cros_ec_i2c_of_match[] = { + { .compatible = "google,cros-ec-i2c", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match); + static const struct i2c_device_id cros_ec_i2c_id[] = { { "cros-ec-i2c", 0 }, { } @@ -353,6 +359,7 @@ MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id); static struct i2c_driver cros_ec_driver = { .driver = { .name = "cros-ec-i2c", + .of_match_table = of_match_ptr(cros_ec_i2c_of_match), .pm = &cros_ec_i2c_pm_ops, }, .probe = cros_ec_i2c_probe, -- cgit v1.2.3 From 62a2e633474107a9ae93dfedf16341ec6414a907 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Tue, 25 Aug 2015 14:34:28 +0530 Subject: mfd: 88pm80x: Add 88pm860 chip type support Add chip identification support for 88PM860 device to the pm80x_chip_mapping table. Signed-off-by: Vaibhav Hiremath Reviewed-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/88pm80x.c | 2 ++ include/linux/mfd/88pm80x.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index 5e72f65ef94c..63445ea6b0bf 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -33,6 +33,8 @@ static struct pm80x_chip_mapping chip_mapping[] = { {0x3, CHIP_PM800}, /* 88PM805 chip id number */ {0x0, CHIP_PM805}, + /* 88PM860 chip id number */ + {0x4, CHIP_PM860}, }; /* diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index 8fcad63fab55..d409ceb2231e 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -21,6 +21,7 @@ enum { CHIP_INVALID = 0, CHIP_PM800, CHIP_PM805, + CHIP_PM860, CHIP_MAX, }; -- cgit v1.2.3 From 75c08f17ec87c2d742487bb87408d6feebc526bd Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 18 Sep 2015 09:29:04 -0700 Subject: mfd: twl6040: Fix deferred probe handling for clk32k Commit 68bab8662f49 ("mfd: twl6040: Optional clk32k clock handling") added clock handling for the 32k clock from palmas-clk. However, that patch did not consider a typical situation where twl6040 is built-in, and palmas-clk is a loadable module like we have in omap2plus_defconfig. If palmas-clk is not loaded before twl6040 probes, we will get a "clk32k is not handled" warning during booting. This means that any drivers relying on this clock will mysteriously fail, including omap5-uevm WLAN and audio. Note that for WLAN, we probably should also eventually get the clk32kgaudio for MMC3 directly as that's shared between audio and WLAN SDIO at least for omap5-uevm. It seems the WLAN chip cannot get it as otherwise MMC3 won't get properly probed. Fixes: 68bab8662f49 ("mfd: twl6040: Optional clk32k clock handling") Signed-off-by: Tony Lindgren Reviewed-by: Felipe Balbi Signed-off-by: Lee Jones --- drivers/mfd/twl6040.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index a151ee2eed2a..08a693cd38cc 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -647,6 +647,8 @@ static int twl6040_probe(struct i2c_client *client, twl6040->clk32k = devm_clk_get(&client->dev, "clk32k"); if (IS_ERR(twl6040->clk32k)) { + if (PTR_ERR(twl6040->clk32k) == -EPROBE_DEFER) + return -EPROBE_DEFER; dev_info(&client->dev, "clk32k is not handled\n"); twl6040->clk32k = NULL; } -- cgit v1.2.3 From f6d10341390d5d5bda1122dc5365e34d78f672ee Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 27 Aug 2015 23:50:02 +0200 Subject: mfd: stmpe: PWM on 24xx has altfunc 1 On the STMPE2401 and STMPE2401 altfunction 1 corresponds to the PWM channels. This oneliner was missing in the case-switch, making it impossible to enable the PWM channel output. Signed-off-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/stmpe.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index e971af86ce1e..8222e374e4b1 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -795,6 +795,7 @@ static int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) return 2; case STMPE_BLOCK_KEYPAD: + case STMPE_BLOCK_PWM: return 1; case STMPE_BLOCK_GPIO: -- cgit v1.2.3 From c6d005ad7989803a2e30f95c81e71575c86543a1 Mon Sep 17 00:00:00 2001 From: Nariman Poushin Date: Fri, 18 Sep 2015 12:55:58 +0100 Subject: mfd: Fixup clients of multi_reg_write/register_patch Introduced by: commit 8019ff6cfc04 ("regmap: Use reg_sequence for multi_reg_write / register_patch") Interacting with: commit 561629755a21 ("mfd: arizona: Add support for WM8998 and WM1814") commit 81207880cef2 ("mfd: wm5110: Add register patch for rev E and above") Signed-off-by: Nariman Poushin Acked-by: Geert Uytterhoeven Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 2 +- drivers/mfd/wm8998-tables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 28f2ae30507a..46cad3280114 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -250,7 +250,7 @@ static const struct reg_sequence wm5110_revd_patch[] = { }; /* Add extra headphone write sequence locations */ -static const struct reg_default wm5110_reve_patch[] = { +static const struct reg_sequence wm5110_reve_patch[] = { { 0x80, 0x3 }, { 0x80, 0x3 }, { 0x4b, 0x138 }, diff --git a/drivers/mfd/wm8998-tables.c b/drivers/mfd/wm8998-tables.c index e6de3cd8a9aa..607640c9c80f 100644 --- a/drivers/mfd/wm8998-tables.c +++ b/drivers/mfd/wm8998-tables.c @@ -21,7 +21,7 @@ #define WM8998_NUM_AOD_ISR 2 #define WM8998_NUM_ISR 5 -static const struct reg_default wm8998_rev_a_patch[] = { +static const struct reg_sequence wm8998_rev_a_patch[] = { { 0x0212, 0x0000 }, { 0x0211, 0x0014 }, { 0x04E4, 0x0E0D }, -- cgit v1.2.3 From a0aef1f529c9caf207176337ff0418a68a32e87f Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Thu, 17 Sep 2015 20:15:44 +0200 Subject: mfd: atmel-hlcdc: Fix module autoload for OF platform driver This platform driver has a OF device ID table but the OF module alias information is not created so module autoloading won't work. Signed-off-by: Luis de Bethencourt Signed-off-by: Lee Jones --- drivers/mfd/atmel-hlcdc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c index 3fff6b5d0426..06c205868573 100644 --- a/drivers/mfd/atmel-hlcdc.c +++ b/drivers/mfd/atmel-hlcdc.c @@ -148,6 +148,7 @@ static const struct of_device_id atmel_hlcdc_match[] = { { .compatible = "atmel,sama5d4-hlcdc" }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(of, atmel_hlcdc_match); static struct platform_driver atmel_hlcdc_driver = { .probe = atmel_hlcdc_probe, -- cgit v1.2.3 From 544507362d2d1bd3514358df6c6df573f023afd7 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Thu, 17 Sep 2015 20:16:10 +0200 Subject: mfd: hi6421-pmic: Fix module autoload for OF platform driver This platform driver has a OF device ID table but the OF module alias information is not created so module autoloading won't work. Signed-off-by: Luis de Bethencourt Signed-off-by: Lee Jones --- drivers/mfd/hi6421-pmic-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/hi6421-pmic-core.c b/drivers/mfd/hi6421-pmic-core.c index 95b2ff8f223a..f9ded45a992d 100644 --- a/drivers/mfd/hi6421-pmic-core.c +++ b/drivers/mfd/hi6421-pmic-core.c @@ -97,6 +97,7 @@ static const struct of_device_id of_hi6421_pmic_match_tbl[] = { { .compatible = "hisilicon,hi6421-pmic", }, { }, }; +MODULE_DEVICE_TABLE(of, of_hi6421_pmic_match_tbl); static struct platform_driver hi6421_pmic_driver = { .driver = { -- cgit v1.2.3 From 01bd09f040698ffbe45e4b8ed7a4399148d2cf9b Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Thu, 17 Sep 2015 20:16:32 +0200 Subject: mfd: max8997: Fix module autoload for OF platform driver This platform driver has a OF device ID table but the OF module alias information is not created so module autoloading won't work. Signed-off-by: Luis de Bethencourt Signed-off-by: Lee Jones --- drivers/mfd/max8997.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index d3cfa9cf5c8f..156ed6f92aa3 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -55,6 +55,7 @@ static const struct of_device_id max8997_pmic_dt_match[] = { { .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 }, {}, }; +MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match); #endif int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest) -- cgit v1.2.3 From 327cc18e76295690f560feb999cd4ec0e5d661d5 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Thu, 17 Sep 2015 20:16:50 +0200 Subject: mfd: sm501: Fix module autoload for OF platform driver This platform driver has a OF device ID table but the OF module alias information is not created so module autoloading won't work. Signed-off-by: Luis de Bethencourt Signed-off-by: Lee Jones --- drivers/mfd/sm501.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 91077efc8050..c646784c5a7d 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -1719,6 +1719,7 @@ static const struct of_device_id of_sm501_match_tbl[] = { { .compatible = "smi,sm501", }, { /* end */ } }; +MODULE_DEVICE_TABLE(of, of_sm501_match_tbl); static struct platform_driver sm501_plat_driver = { .driver = { -- cgit v1.2.3 From 689d4453ed8212ab4a5d53982ac01cbe6531d18a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 14 Sep 2015 11:32:48 +0300 Subject: mfd: intel-lpss: Use writeq() helper There are already helper functions to do 64-bit I/O on 32-bit machines, thus we don't need to reinvent the wheel. In our case we can't use readq() / writeq() even on 64-bit kernel since there is a hardware limitation (OCP bus is a 32-bit bus). Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index fdf4d5c1add2..001a7d7708ce 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -26,6 +26,8 @@ #include #include +#include + #include "intel-lpss.h" #define LPSS_DEV_OFFSET 0x000 @@ -52,8 +54,7 @@ #define LPSS_PRIV_SSP_REG 0x20 #define LPSS_PRIV_SSP_REG_DIS_DMA_FIN BIT(0) -#define LPSS_PRIV_REMAP_ADDR_LO 0x40 -#define LPSS_PRIV_REMAP_ADDR_HI 0x44 +#define LPSS_PRIV_REMAP_ADDR 0x40 #define LPSS_PRIV_CAPS 0xfc #define LPSS_PRIV_CAPS_NO_IDMA BIT(8) @@ -250,12 +251,7 @@ static void intel_lpss_set_remap_addr(const struct intel_lpss *lpss) { resource_size_t addr = lpss->info->mem->start; - writel(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR_LO); -#if BITS_PER_LONG > 32 - writel(addr >> 32, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI); -#else - writel(0, lpss->priv + LPSS_PRIV_REMAP_ADDR_HI); -#endif + lo_hi_writeq(addr, lpss->priv + LPSS_PRIV_REMAP_ADDR); } static void intel_lpss_deassert_reset(const struct intel_lpss *lpss) -- cgit v1.2.3 From d785334a0d5deff30a487c74324b842d2179553d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 14 Sep 2015 21:12:45 +0900 Subject: mfd: s2mps11: Add manual shutdown method for Odroid XU3 On Odroid XU3 board (with S2MPS11 PMIC) the PWRHOLD bit in CTRL1 register must be manually set to 0 before initiating power off sequence. One of usual power down methods for Exynos based devices looks like: 1. PWRHOLD pin of PMIC is connected to PSHOLD of Exynos SoC. 2. Exynos holds up this pin during system operation. 3. ACOKB pin of PMIC is pulled up to VBATT and optionally to pin in other device. 4. When PWRHOLD/PSHOLD goes low, the PMIC will turn off the power if ACOKB goes high. On Odroid XU3 family the difference is in (3) - the ACOKB is grounded. This means that PMIC must manually set PWRHOLD field to low and then wait for signal from Application Processor (the usual change in PWRHOLD/PSHOLD pin will actually cut off the power). The patch adds respective binding allowing Odroid XU3 device to be powered off. Signed-off-by: Krzysztof Kozlowski Reported-by: Anand Moon Tested-by: Anand Moon Reviewed-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 30 ++++++++++++++++++++++++++++++ include/linux/mfd/samsung/core.h | 2 ++ include/linux/mfd/samsung/s2mps11.h | 1 + 3 files changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index d206a3e8fe87..2d1137a7a0ee 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -278,6 +278,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( * not parsed here. */ + pd->manual_poweroff = of_property_read_bool(dev->of_node, + "samsung,s2mps11-acokb-ground"); return pd; } #else @@ -440,6 +442,33 @@ static int sec_pmic_remove(struct i2c_client *i2c) return 0; } +static void sec_pmic_shutdown(struct i2c_client *i2c) +{ + struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + unsigned int reg, mask; + + if (!sec_pmic->pdata->manual_poweroff) + return; + + switch (sec_pmic->device_type) { + case S2MPS11X: + reg = S2MPS11_REG_CTRL1; + mask = S2MPS11_CTRL1_PWRHOLD_MASK; + break; + default: + /* + * Currently only one board with S2MPS11 needs this, so just + * ignore the rest. + */ + dev_warn(sec_pmic->dev, + "Unsupported device %lu for manual power off\n", + sec_pmic->device_type); + return; + } + + regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0); +} + #ifdef CONFIG_PM_SLEEP static int sec_pmic_suspend(struct device *dev) { @@ -491,6 +520,7 @@ static struct i2c_driver sec_pmic_driver = { }, .probe = sec_pmic_probe, .remove = sec_pmic_remove, + .shutdown = sec_pmic_shutdown, .id_table = sec_pmic_id, }; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 75115384f3fc..aa78957e092f 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -132,6 +132,8 @@ struct sec_platform_data { int buck2_init; int buck3_init; int buck4_init; + /* Whether or not manually set PWRHOLD to low during shutdown. */ + bool manual_poweroff; }; /** diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index 7981a9d77d3f..b288965e8101 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -179,6 +179,7 @@ enum s2mps11_regulators { #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) #define S2MPS11_RAMP_DELAY 25000 /* uV/us */ +#define S2MPS11_CTRL1_PWRHOLD_MASK BIT(4) #define S2MPS11_BUCK2_RAMP_SHIFT 6 #define S2MPS11_BUCK34_RAMP_SHIFT 4 -- cgit v1.2.3 From 16dfd10375011e0999ce9d96df2df08380edf001 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 14 Sep 2015 11:07:56 +0200 Subject: mfd: wm831x: Fix possible NULL pointer dereference The driver always checks for pdata being NULL except in one place. Add a check to prevent a possible NULL pointer deference error. Signed-off-by: Javier Martinez Canillas Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm831x-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 28366a90e1ad..3e0e99ec5836 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -1626,7 +1626,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) mutex_init(&wm831x->io_lock); mutex_init(&wm831x->key_lock); dev_set_drvdata(wm831x->dev, wm831x); - wm831x->soft_shutdown = pdata->soft_shutdown; + + if (pdata) + wm831x->soft_shutdown = pdata->soft_shutdown; ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); if (ret < 0) { -- cgit v1.2.3 From 0a464dfdf8dec7410bd6bc8af9086098ee712a04 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 11 Sep 2015 16:07:56 +0100 Subject: mfd: arizona: Fix typo in arizona_irq_map The type of the data for the main Arizona IRQ chip should be struct arizona not struct regmap_irq_chip_data. The bug is harmless but should probably be corrected anyway. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 2cac4f463f1e..3d425e93ce84 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -169,7 +169,7 @@ static struct irq_chip arizona_irq_chip = { static int arizona_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { - struct regmap_irq_chip_data *data = h->host_data; + struct arizona *data = h->host_data; irq_set_chip_data(virq, data); irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq); -- cgit v1.2.3 From 9111fa5c4032589e9b7ccc01e330810ba05726bf Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 9 Sep 2015 09:49:22 +0100 Subject: mfd: arizona: Add register bits to support the ANC block Some Arizona devices have a hardware ANC block present. This patch adds the registers necessary to configure this hardware block. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm5110-tables.c | 186 ++++++++++++++++++++++++++++++++++ include/linux/mfd/arizona/registers.h | 70 +++++++++++++ 2 files changed, 256 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index 46cad3280114..2bb2d0467a92 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c @@ -1633,6 +1633,185 @@ static const struct reg_default wm5110_reg_default[] = { { 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */ { 0x00000F00, 0x0000 }, /* R3840 - Clock Control */ { 0x00000F01, 0x0000 }, /* R3841 - ANC_SRC */ + { 0x00000F08, 0x001c }, /* R3848 - ANC Coefficient */ + { 0x00000F09, 0x0000 }, /* R3849 - ANC Coefficient */ + { 0x00000F0A, 0x0000 }, /* R3850 - ANC Coefficient */ + { 0x00000F0B, 0x0000 }, /* R3851 - ANC Coefficient */ + { 0x00000F0C, 0x0000 }, /* R3852 - ANC Coefficient */ + { 0x00000F0D, 0x0000 }, /* R3853 - ANC Coefficient */ + { 0x00000F0E, 0x0000 }, /* R3854 - ANC Coefficient */ + { 0x00000F0F, 0x0000 }, /* R3855 - ANC Coefficient */ + { 0x00000F10, 0x0000 }, /* R3856 - ANC Coefficient */ + { 0x00000F11, 0x0000 }, /* R3857 - ANC Coefficient */ + { 0x00000F12, 0x0000 }, /* R3858 - ANC Coefficient */ + { 0x00000F15, 0x0000 }, /* R3861 - FCL Filter Control */ + { 0x00000F17, 0x0004 }, /* R3863 - FCL ADC Reformatter Control */ + { 0x00000F18, 0x0004 }, /* R3864 - ANC Coefficient */ + { 0x00000F19, 0x0002 }, /* R3865 - ANC Coefficient */ + { 0x00000F1A, 0x0000 }, /* R3866 - ANC Coefficient */ + { 0x00000F1B, 0x0010 }, /* R3867 - ANC Coefficient */ + { 0x00000F1C, 0x0000 }, /* R3868 - ANC Coefficient */ + { 0x00000F1D, 0x0000 }, /* R3869 - ANC Coefficient */ + { 0x00000F1E, 0x0000 }, /* R3870 - ANC Coefficient */ + { 0x00000F1F, 0x0000 }, /* R3871 - ANC Coefficient */ + { 0x00000F20, 0x0000 }, /* R3872 - ANC Coefficient */ + { 0x00000F21, 0x0000 }, /* R3873 - ANC Coefficient */ + { 0x00000F22, 0x0000 }, /* R3874 - ANC Coefficient */ + { 0x00000F23, 0x0000 }, /* R3875 - ANC Coefficient */ + { 0x00000F24, 0x0000 }, /* R3876 - ANC Coefficient */ + { 0x00000F25, 0x0000 }, /* R3877 - ANC Coefficient */ + { 0x00000F26, 0x0000 }, /* R3878 - ANC Coefficient */ + { 0x00000F27, 0x0000 }, /* R3879 - ANC Coefficient */ + { 0x00000F28, 0x0000 }, /* R3880 - ANC Coefficient */ + { 0x00000F29, 0x0000 }, /* R3881 - ANC Coefficient */ + { 0x00000F2A, 0x0000 }, /* R3882 - ANC Coefficient */ + { 0x00000F2B, 0x0000 }, /* R3883 - ANC Coefficient */ + { 0x00000F2C, 0x0000 }, /* R3884 - ANC Coefficient */ + { 0x00000F2D, 0x0000 }, /* R3885 - ANC Coefficient */ + { 0x00000F2E, 0x0000 }, /* R3886 - ANC Coefficient */ + { 0x00000F2F, 0x0000 }, /* R3887 - ANC Coefficient */ + { 0x00000F30, 0x0000 }, /* R3888 - ANC Coefficient */ + { 0x00000F31, 0x0000 }, /* R3889 - ANC Coefficient */ + { 0x00000F32, 0x0000 }, /* R3890 - ANC Coefficient */ + { 0x00000F33, 0x0000 }, /* R3891 - ANC Coefficient */ + { 0x00000F34, 0x0000 }, /* R3892 - ANC Coefficient */ + { 0x00000F35, 0x0000 }, /* R3893 - ANC Coefficient */ + { 0x00000F36, 0x0000 }, /* R3894 - ANC Coefficient */ + { 0x00000F37, 0x0000 }, /* R3895 - ANC Coefficient */ + { 0x00000F38, 0x0000 }, /* R3896 - ANC Coefficient */ + { 0x00000F39, 0x0000 }, /* R3897 - ANC Coefficient */ + { 0x00000F3A, 0x0000 }, /* R3898 - ANC Coefficient */ + { 0x00000F3B, 0x0000 }, /* R3899 - ANC Coefficient */ + { 0x00000F3C, 0x0000 }, /* R3900 - ANC Coefficient */ + { 0x00000F3D, 0x0000 }, /* R3901 - ANC Coefficient */ + { 0x00000F3E, 0x0000 }, /* R3902 - ANC Coefficient */ + { 0x00000F3F, 0x0000 }, /* R3903 - ANC Coefficient */ + { 0x00000F40, 0x0000 }, /* R3904 - ANC Coefficient */ + { 0x00000F41, 0x0000 }, /* R3905 - ANC Coefficient */ + { 0x00000F42, 0x0000 }, /* R3906 - ANC Coefficient */ + { 0x00000F43, 0x0000 }, /* R3907 - ANC Coefficient */ + { 0x00000F44, 0x0000 }, /* R3908 - ANC Coefficient */ + { 0x00000F45, 0x0000 }, /* R3909 - ANC Coefficient */ + { 0x00000F46, 0x0000 }, /* R3910 - ANC Coefficient */ + { 0x00000F47, 0x0000 }, /* R3911 - ANC Coefficient */ + { 0x00000F48, 0x0000 }, /* R3912 - ANC Coefficient */ + { 0x00000F49, 0x0000 }, /* R3913 - ANC Coefficient */ + { 0x00000F4A, 0x0000 }, /* R3914 - ANC Coefficient */ + { 0x00000F4B, 0x0000 }, /* R3915 - ANC Coefficient */ + { 0x00000F4C, 0x0000 }, /* R3916 - ANC Coefficient */ + { 0x00000F4D, 0x0000 }, /* R3917 - ANC Coefficient */ + { 0x00000F4E, 0x0000 }, /* R3918 - ANC Coefficient */ + { 0x00000F4F, 0x0000 }, /* R3919 - ANC Coefficient */ + { 0x00000F50, 0x0000 }, /* R3920 - ANC Coefficient */ + { 0x00000F51, 0x0000 }, /* R3921 - ANC Coefficient */ + { 0x00000F52, 0x0000 }, /* R3922 - ANC Coefficient */ + { 0x00000F53, 0x0000 }, /* R3923 - ANC Coefficient */ + { 0x00000F54, 0x0000 }, /* R3924 - ANC Coefficient */ + { 0x00000F55, 0x0000 }, /* R3925 - ANC Coefficient */ + { 0x00000F56, 0x0000 }, /* R3926 - ANC Coefficient */ + { 0x00000F57, 0x0000 }, /* R3927 - ANC Coefficient */ + { 0x00000F58, 0x0000 }, /* R3928 - ANC Coefficient */ + { 0x00000F59, 0x0000 }, /* R3929 - ANC Coefficient */ + { 0x00000F5A, 0x0000 }, /* R3930 - ANC Coefficient */ + { 0x00000F5B, 0x0000 }, /* R3931 - ANC Coefficient */ + { 0x00000F5C, 0x0000 }, /* R3932 - ANC Coefficient */ + { 0x00000F5D, 0x0000 }, /* R3933 - ANC Coefficient */ + { 0x00000F5E, 0x0000 }, /* R3934 - ANC Coefficient */ + { 0x00000F5F, 0x0000 }, /* R3935 - ANC Coefficient */ + { 0x00000F60, 0x0000 }, /* R3936 - ANC Coefficient */ + { 0x00000F61, 0x0000 }, /* R3937 - ANC Coefficient */ + { 0x00000F62, 0x0000 }, /* R3938 - ANC Coefficient */ + { 0x00000F63, 0x0000 }, /* R3939 - ANC Coefficient */ + { 0x00000F64, 0x0000 }, /* R3940 - ANC Coefficient */ + { 0x00000F65, 0x0000 }, /* R3941 - ANC Coefficient */ + { 0x00000F66, 0x0000 }, /* R3942 - ANC Coefficient */ + { 0x00000F67, 0x0000 }, /* R3943 - ANC Coefficient */ + { 0x00000F68, 0x0000 }, /* R3944 - ANC Coefficient */ + { 0x00000F69, 0x0000 }, /* R3945 - ANC Coefficient */ + { 0x00000F70, 0x0000 }, /* R3952 - FCR Filter Control */ + { 0x00000F72, 0x0004 }, /* R3954 - FCR ADC Reformatter Control */ + { 0x00000F73, 0x0004 }, /* R3955 - ANC Coefficient */ + { 0x00000F74, 0x0002 }, /* R3956 - ANC Coefficient */ + { 0x00000F75, 0x0000 }, /* R3957 - ANC Coefficient */ + { 0x00000F76, 0x0010 }, /* R3958 - ANC Coefficient */ + { 0x00000F77, 0x0000 }, /* R3959 - ANC Coefficient */ + { 0x00000F78, 0x0000 }, /* R3960 - ANC Coefficient */ + { 0x00000F79, 0x0000 }, /* R3961 - ANC Coefficient */ + { 0x00000F7A, 0x0000 }, /* R3962 - ANC Coefficient */ + { 0x00000F7B, 0x0000 }, /* R3963 - ANC Coefficient */ + { 0x00000F7C, 0x0000 }, /* R3964 - ANC Coefficient */ + { 0x00000F7D, 0x0000 }, /* R3965 - ANC Coefficient */ + { 0x00000F7E, 0x0000 }, /* R3966 - ANC Coefficient */ + { 0x00000F7F, 0x0000 }, /* R3967 - ANC Coefficient */ + { 0x00000F80, 0x0000 }, /* R3968 - ANC Coefficient */ + { 0x00000F81, 0x0000 }, /* R3969 - ANC Coefficient */ + { 0x00000F82, 0x0000 }, /* R3970 - ANC Coefficient */ + { 0x00000F83, 0x0000 }, /* R3971 - ANC Coefficient */ + { 0x00000F84, 0x0000 }, /* R3972 - ANC Coefficient */ + { 0x00000F85, 0x0000 }, /* R3973 - ANC Coefficient */ + { 0x00000F86, 0x0000 }, /* R3974 - ANC Coefficient */ + { 0x00000F87, 0x0000 }, /* R3975 - ANC Coefficient */ + { 0x00000F88, 0x0000 }, /* R3976 - ANC Coefficient */ + { 0x00000F89, 0x0000 }, /* R3977 - ANC Coefficient */ + { 0x00000F8A, 0x0000 }, /* R3978 - ANC Coefficient */ + { 0x00000F8B, 0x0000 }, /* R3979 - ANC Coefficient */ + { 0x00000F8C, 0x0000 }, /* R3980 - ANC Coefficient */ + { 0x00000F8D, 0x0000 }, /* R3981 - ANC Coefficient */ + { 0x00000F8E, 0x0000 }, /* R3982 - ANC Coefficient */ + { 0x00000F8F, 0x0000 }, /* R3983 - ANC Coefficient */ + { 0x00000F90, 0x0000 }, /* R3984 - ANC Coefficient */ + { 0x00000F91, 0x0000 }, /* R3985 - ANC Coefficient */ + { 0x00000F92, 0x0000 }, /* R3986 - ANC Coefficient */ + { 0x00000F93, 0x0000 }, /* R3987 - ANC Coefficient */ + { 0x00000F94, 0x0000 }, /* R3988 - ANC Coefficient */ + { 0x00000F95, 0x0000 }, /* R3989 - ANC Coefficient */ + { 0x00000F96, 0x0000 }, /* R3990 - ANC Coefficient */ + { 0x00000F97, 0x0000 }, /* R3991 - ANC Coefficient */ + { 0x00000F98, 0x0000 }, /* R3992 - ANC Coefficient */ + { 0x00000F99, 0x0000 }, /* R3993 - ANC Coefficient */ + { 0x00000F9A, 0x0000 }, /* R3994 - ANC Coefficient */ + { 0x00000F9B, 0x0000 }, /* R3995 - ANC Coefficient */ + { 0x00000F9C, 0x0000 }, /* R3996 - ANC Coefficient */ + { 0x00000F9D, 0x0000 }, /* R3997 - ANC Coefficient */ + { 0x00000F9E, 0x0000 }, /* R3998 - ANC Coefficient */ + { 0x00000F9F, 0x0000 }, /* R3999 - ANC Coefficient */ + { 0x00000FA0, 0x0000 }, /* R4000 - ANC Coefficient */ + { 0x00000FA1, 0x0000 }, /* R4001 - ANC Coefficient */ + { 0x00000FA2, 0x0000 }, /* R4002 - ANC Coefficient */ + { 0x00000FA3, 0x0000 }, /* R4003 - ANC Coefficient */ + { 0x00000FA4, 0x0000 }, /* R4004 - ANC Coefficient */ + { 0x00000FA5, 0x0000 }, /* R4005 - ANC Coefficient */ + { 0x00000FA6, 0x0000 }, /* R4006 - ANC Coefficient */ + { 0x00000FA7, 0x0000 }, /* R4007 - ANC Coefficient */ + { 0x00000FA8, 0x0000 }, /* R4008 - ANC Coefficient */ + { 0x00000FA9, 0x0000 }, /* R4009 - ANC Coefficient */ + { 0x00000FAA, 0x0000 }, /* R4010 - ANC Coefficient */ + { 0x00000FAB, 0x0000 }, /* R4011 - ANC Coefficient */ + { 0x00000FAC, 0x0000 }, /* R4012 - ANC Coefficient */ + { 0x00000FAD, 0x0000 }, /* R4013 - ANC Coefficient */ + { 0x00000FAE, 0x0000 }, /* R4014 - ANC Coefficient */ + { 0x00000FAF, 0x0000 }, /* R4015 - ANC Coefficient */ + { 0x00000FB0, 0x0000 }, /* R4016 - ANC Coefficient */ + { 0x00000FB1, 0x0000 }, /* R4017 - ANC Coefficient */ + { 0x00000FB2, 0x0000 }, /* R4018 - ANC Coefficient */ + { 0x00000FB3, 0x0000 }, /* R4019 - ANC Coefficient */ + { 0x00000FB4, 0x0000 }, /* R4020 - ANC Coefficient */ + { 0x00000FB5, 0x0000 }, /* R4021 - ANC Coefficient */ + { 0x00000FB6, 0x0000 }, /* R4022 - ANC Coefficient */ + { 0x00000FB7, 0x0000 }, /* R4023 - ANC Coefficient */ + { 0x00000FB8, 0x0000 }, /* R4024 - ANC Coefficient */ + { 0x00000FB9, 0x0000 }, /* R4025 - ANC Coefficient */ + { 0x00000FBA, 0x0000 }, /* R4026 - ANC Coefficient */ + { 0x00000FBB, 0x0000 }, /* R4027 - ANC Coefficient */ + { 0x00000FBC, 0x0000 }, /* R4028 - ANC Coefficient */ + { 0x00000FBD, 0x0000 }, /* R4029 - ANC Coefficient */ + { 0x00000FBE, 0x0000 }, /* R4030 - ANC Coefficient */ + { 0x00000FBF, 0x0000 }, /* R4031 - ANC Coefficient */ + { 0x00000FC0, 0x0000 }, /* R4032 - ANC Coefficient */ + { 0x00000FC1, 0x0000 }, /* R4033 - ANC Coefficient */ + { 0x00000FC2, 0x0000 }, /* R4034 - ANC Coefficient */ + { 0x00000FC3, 0x0000 }, /* R4035 - ANC Coefficient */ + { 0x00000FC4, 0x0000 }, /* R4036 - ANC Coefficient */ { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ { 0x00001200, 0x0010 }, /* R4608 - DSP2 Control 1 */ { 0x00001300, 0x0010 }, /* R4864 - DSP3 Control 1 */ @@ -2710,6 +2889,13 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg) case ARIZONA_CLOCK_CONTROL: case ARIZONA_ANC_SRC: case ARIZONA_DSP_STATUS: + case ARIZONA_ANC_COEFF_START ... ARIZONA_ANC_COEFF_END: + case ARIZONA_FCL_FILTER_CONTROL: + case ARIZONA_FCL_ADC_REFORMATTER_CONTROL: + case ARIZONA_FCL_COEFF_START ... ARIZONA_FCL_COEFF_END: + case ARIZONA_FCR_FILTER_CONTROL: + case ARIZONA_FCR_ADC_REFORMATTER_CONTROL: + case ARIZONA_FCR_COEFF_START ... ARIZONA_FCR_COEFF_END: case ARIZONA_DSP1_CONTROL_1: case ARIZONA_DSP1_CLOCKING_1: case ARIZONA_DSP1_STATUS_1: diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h index c7c11c900196..cd7e78eae006 100644 --- a/include/linux/mfd/arizona/registers.h +++ b/include/linux/mfd/arizona/registers.h @@ -1065,6 +1065,16 @@ #define ARIZONA_CLOCK_CONTROL 0xF00 #define ARIZONA_ANC_SRC 0xF01 #define ARIZONA_DSP_STATUS 0xF02 +#define ARIZONA_ANC_COEFF_START 0xF08 +#define ARIZONA_ANC_COEFF_END 0xF12 +#define ARIZONA_FCL_FILTER_CONTROL 0xF15 +#define ARIZONA_FCL_ADC_REFORMATTER_CONTROL 0xF17 +#define ARIZONA_FCL_COEFF_START 0xF18 +#define ARIZONA_FCL_COEFF_END 0xF69 +#define ARIZONA_FCR_FILTER_CONTROL 0xF70 +#define ARIZONA_FCR_ADC_REFORMATTER_CONTROL 0xF72 +#define ARIZONA_FCR_COEFF_START 0xF73 +#define ARIZONA_FCR_COEFF_END 0xFC4 #define ARIZONA_DSP1_CONTROL_1 0x1100 #define ARIZONA_DSP1_CLOCKING_1 0x1101 #define ARIZONA_DSP1_STATUS_1 0x1104 @@ -8050,6 +8060,66 @@ #define ARIZONA_ISRC3_NOTCH_ENA_SHIFT 0 /* ISRC3_NOTCH_ENA */ #define ARIZONA_ISRC3_NOTCH_ENA_WIDTH 1 /* ISRC3_NOTCH_ENA */ +/* + * R3840 (0xF00) - Clock Control + */ +#define ARIZONA_EXT_NG_SEL_CLR 0x0080 /* EXT_NG_SEL_CLR */ +#define ARIZONA_EXT_NG_SEL_CLR_MASK 0x0080 /* EXT_NG_SEL_CLR */ +#define ARIZONA_EXT_NG_SEL_CLR_SHIFT 7 /* EXT_NG_SEL_CLR */ +#define ARIZONA_EXT_NG_SEL_CLR_WIDTH 1 /* EXT_NG_SEL_CLR */ +#define ARIZONA_EXT_NG_SEL_SET 0x0040 /* EXT_NG_SEL_SET */ +#define ARIZONA_EXT_NG_SEL_SET_MASK 0x0040 /* EXT_NG_SEL_SET */ +#define ARIZONA_EXT_NG_SEL_SET_SHIFT 6 /* EXT_NG_SEL_SET */ +#define ARIZONA_EXT_NG_SEL_SET_WIDTH 1 /* EXT_NG_SEL_SET */ +#define ARIZONA_CLK_R_ENA_CLR 0x0020 /* CLK_R_ENA_CLR */ +#define ARIZONA_CLK_R_ENA_CLR_MASK 0x0020 /* CLK_R_ENA_CLR */ +#define ARIZONA_CLK_R_ENA_CLR_SHIFT 5 /* CLK_R_ENA_CLR */ +#define ARIZONA_CLK_R_ENA_CLR_WIDTH 1 /* CLK_R_ENA_CLR */ +#define ARIZONA_CLK_R_ENA_SET 0x0010 /* CLK_R_ENA_SET */ +#define ARIZONA_CLK_R_ENA_SET_MASK 0x0010 /* CLK_R_ENA_SET */ +#define ARIZONA_CLK_R_ENA_SET_SHIFT 4 /* CLK_R_ENA_SET */ +#define ARIZONA_CLK_R_ENA_SET_WIDTH 1 /* CLK_R_ENA_SET */ +#define ARIZONA_CLK_NG_ENA_CLR 0x0008 /* CLK_NG_ENA_CLR */ +#define ARIZONA_CLK_NG_ENA_CLR_MASK 0x0008 /* CLK_NG_ENA_CLR */ +#define ARIZONA_CLK_NG_ENA_CLR_SHIFT 3 /* CLK_NG_ENA_CLR */ +#define ARIZONA_CLK_NG_ENA_CLR_WIDTH 1 /* CLK_NG_ENA_CLR */ +#define ARIZONA_CLK_NG_ENA_SET 0x0004 /* CLK_NG_ENA_SET */ +#define ARIZONA_CLK_NG_ENA_SET_MASK 0x0004 /* CLK_NG_ENA_SET */ +#define ARIZONA_CLK_NG_ENA_SET_SHIFT 2 /* CLK_NG_ENA_SET */ +#define ARIZONA_CLK_NG_ENA_SET_WIDTH 1 /* CLK_NG_ENA_SET */ +#define ARIZONA_CLK_L_ENA_CLR 0x0002 /* CLK_L_ENA_CLR */ +#define ARIZONA_CLK_L_ENA_CLR_MASK 0x0002 /* CLK_L_ENA_CLR */ +#define ARIZONA_CLK_L_ENA_CLR_SHIFT 1 /* CLK_L_ENA_CLR */ +#define ARIZONA_CLK_L_ENA_CLR_WIDTH 1 /* CLK_L_ENA_CLR */ +#define ARIZONA_CLK_L_ENA_SET 0x0001 /* CLK_L_ENA_SET */ +#define ARIZONA_CLK_L_ENA_SET_MASK 0x0001 /* CLK_L_ENA_SET */ +#define ARIZONA_CLK_L_ENA_SET_SHIFT 0 /* CLK_L_ENA_SET */ +#define ARIZONA_CLK_L_ENA_SET_WIDTH 1 /* CLK_L_ENA_SET */ + +/* + * R3841 (0xF01) - ANC SRC + */ +#define ARIZONA_IN_RXANCR_SEL_MASK 0x0070 /* IN_RXANCR_SEL - [4:6] */ +#define ARIZONA_IN_RXANCR_SEL_SHIFT 4 /* IN_RXANCR_SEL - [4:6] */ +#define ARIZONA_IN_RXANCR_SEL_WIDTH 3 /* IN_RXANCR_SEL - [4:6] */ +#define ARIZONA_IN_RXANCL_SEL_MASK 0x0007 /* IN_RXANCL_SEL - [0:2] */ +#define ARIZONA_IN_RXANCL_SEL_SHIFT 0 /* IN_RXANCL_SEL - [0:2] */ +#define ARIZONA_IN_RXANCL_SEL_WIDTH 3 /* IN_RXANCL_SEL - [0:2] */ + +/* + * R3863 (0xF17) - FCL ADC Reformatter Control + */ +#define ARIZONA_FCL_MIC_MODE_SEL 0x000C /* FCL_MIC_MODE_SEL - [2:3] */ +#define ARIZONA_FCL_MIC_MODE_SEL_SHIFT 2 /* FCL_MIC_MODE_SEL - [2:3] */ +#define ARIZONA_FCL_MIC_MODE_SEL_WIDTH 2 /* FCL_MIC_MODE_SEL - [2:3] */ + +/* + * R3954 (0xF72) - FCR ADC Reformatter Control + */ +#define ARIZONA_FCR_MIC_MODE_SEL 0x000C /* FCR_MIC_MODE_SEL - [2:3] */ +#define ARIZONA_FCR_MIC_MODE_SEL_SHIFT 2 /* FCR_MIC_MODE_SEL - [2:3] */ +#define ARIZONA_FCR_MIC_MODE_SEL_WIDTH 2 /* FCR_MIC_MODE_SEL - [2:3] */ + /* * R4352 (0x1100) - DSP1 Control 1 */ -- cgit v1.2.3 From 26fade40a0391f0fc2a49a7c597120e76e41a1ec Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 9 Sep 2015 09:39:30 +0100 Subject: mfd: wm8998: Fixup register defaults/readables Remove defaults for a bunch of volatile registers and remove ARIZONA_CTRL_IF_SPI_CFG_1 from the readable list since it doesn't exist on wm8998 which is I2C only. Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/wm8998-tables.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8998-tables.c b/drivers/mfd/wm8998-tables.c index 607640c9c80f..4c2dce77cdfc 100644 --- a/drivers/mfd/wm8998-tables.c +++ b/drivers/mfd/wm8998-tables.c @@ -199,8 +199,6 @@ static const struct reg_default wm8998_reg_default[] = { { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */ { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */ { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */ - { 0x0000006E, 0x01FF }, /* R110 - Trigger Sequence Select 32 */ - { 0x0000006F, 0x01FF }, /* R111 - Trigger Sequence Select 33 */ { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */ @@ -270,16 +268,13 @@ static const struct reg_default wm8998_reg_default[] = { { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ { 0x00000293, 0x0080 }, /* R659 - Accessory Detect Mode 1 */ { 0x0000029B, 0x0000 }, /* R667 - Headphone Detect 1 */ - { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */ { 0x000002A2, 0x0000 }, /* R674 - Micd Clamp control */ { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ - { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */ { 0x000002A6, 0x3737 }, /* R678 - Mic Detect Level 1 */ { 0x000002A7, 0x2C37 }, /* R679 - Mic Detect Level 2 */ { 0x000002A8, 0x1422 }, /* R680 - Mic Detect Level 3 */ { 0x000002A9, 0x030A }, /* R681 - Mic Detect Level 4 */ - { 0x000002AB, 0x0000 }, /* R683 - Mic Detect 4 */ { 0x000002CB, 0x0000 }, /* R715 - Isolation control */ { 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */ { 0x00000300, 0x0000 }, /* R768 - Input Enables */ @@ -707,13 +702,11 @@ static const struct reg_default wm8998_reg_default[] = { { 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */ { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ { 0x00000D1C, 0xFEFF }, /* R3356 - IRQ2 Status 5 Mask */ - { 0x00000D1D, 0xFFFF }, /* R3357 - IRQ2 Status 6 Mask */ { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */ - { 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */ { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */ { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */ { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */ @@ -833,7 +826,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg) switch (reg) { case ARIZONA_SOFTWARE_RESET: case ARIZONA_DEVICE_REVISION: - case ARIZONA_CTRL_IF_SPI_CFG_1: case ARIZONA_CTRL_IF_I2C1_CFG_1: case ARIZONA_CTRL_IF_I2C1_CFG_2: case ARIZONA_WRITE_SEQUENCER_CTRL_0: -- cgit v1.2.3 From 55cec67aa3ddb7bfb5043ce1540db8839059ccb7 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Tue, 8 Sep 2015 10:09:39 +0200 Subject: mfd: tps65217: Add battery charger as subdevice Add tps65217 battery charger subdevice. Signed-off-by: Enric Balletbo i Serra Signed-off-by: Lee Jones --- drivers/mfd/tps65217.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 55add0453ae9..d32b54426b70 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c @@ -39,6 +39,10 @@ static const struct mfd_cell tps65217s[] = { .name = "tps65217-bl", .of_compatible = "ti,tps65217-bl", }, + { + .name = "tps65217-charger", + .of_compatible = "ti,tps65217-charger", + }, }; /** -- cgit v1.2.3 From 9828ab4711d6e605ecb565c995123ed849908553 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 31 Aug 2015 00:58:29 +0200 Subject: mfd: bcm590xx: Remove unnecessary MODULE_ALIAS() The driver has a I2C device id table that is used to create the module aliases and also "bcm590xx" isn't a supported I2C id, so it's never used. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/bcm590xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c index da2af5b4f855..320aaefee718 100644 --- a/drivers/mfd/bcm590xx.c +++ b/drivers/mfd/bcm590xx.c @@ -128,4 +128,3 @@ module_i2c_driver(bcm590xx_i2c_driver); MODULE_AUTHOR("Matt Porter "); MODULE_DESCRIPTION("BCM590xx multi-function driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("i2c:bcm590xx"); -- cgit v1.2.3 From 4a322296680e560a8ff7eb05c1e58a8cf8497344 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 31 Aug 2015 00:58:30 +0200 Subject: mfd: rt5033: Remove unnecessary MODULE_ALIAS() The driver has a I2C device id table that is used to create the module aliases which already contains a "rt5033". So the alias is not needed. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/rt5033.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index d60f91619c4a..110de2a583af 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -137,7 +137,6 @@ static struct i2c_driver rt5033_driver = { }; module_i2c_driver(rt5033_driver); -MODULE_ALIAS("i2c:rt5033"); MODULE_DESCRIPTION("Richtek RT5033 multi-function core driver"); MODULE_AUTHOR("Beomho Seo "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 39d047c0b1c812e9f0014e7100e372e61f2de3de Mon Sep 17 00:00:00 2001 From: Qipeng Zha Date: Tue, 15 Sep 2015 00:39:19 +0800 Subject: mfd: add Intel Broxton Whiskey Cove PMIC driver Add MFD core driver for Intel Broxton Whiskey Cove PMIC, which is specially accessed by hardware IPC, not a generic I2C device Signed-off-by: Qipeng Zha Signed-off-by: Lee Jones --- drivers/mfd/Makefile | 1 + drivers/mfd/intel_soc_pmic_bxtwc.c | 478 +++++++++++++++++++++++++++++++++++++ include/linux/mfd/intel_bxtwc.h | 69 ++++++ 3 files changed, 548 insertions(+) create mode 100644 drivers/mfd/intel_soc_pmic_bxtwc.c create mode 100644 include/linux/mfd/intel_bxtwc.h (limited to 'drivers') diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index a59e3fcc8626..d6c21e3c409f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -190,5 +190,6 @@ obj-$(CONFIG_MFD_RT5033) += rt5033.o obj-$(CONFIG_MFD_SKY81452) += sky81452.o intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o +intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c new file mode 100644 index 000000000000..40acaff2e1c3 --- /dev/null +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -0,0 +1,478 @@ +/* + * MFD core driver for Intel Broxton Whiskey Cove PMIC + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* PMIC device registers */ +#define REG_ADDR_MASK 0xFF00 +#define REG_ADDR_SHIFT 8 +#define REG_OFFSET_MASK 0xFF + +/* Interrupt Status Registers */ +#define BXTWC_IRQLVL1 0x4E02 +#define BXTWC_PWRBTNIRQ 0x4E03 + +#define BXTWC_THRM0IRQ 0x4E04 +#define BXTWC_THRM1IRQ 0x4E05 +#define BXTWC_THRM2IRQ 0x4E06 +#define BXTWC_BCUIRQ 0x4E07 +#define BXTWC_ADCIRQ 0x4E08 +#define BXTWC_CHGR0IRQ 0x4E09 +#define BXTWC_CHGR1IRQ 0x4E0A +#define BXTWC_GPIOIRQ0 0x4E0B +#define BXTWC_GPIOIRQ1 0x4E0C +#define BXTWC_CRITIRQ 0x4E0D + +/* Interrupt MASK Registers */ +#define BXTWC_MIRQLVL1 0x4E0E +#define BXTWC_MPWRTNIRQ 0x4E0F + +#define BXTWC_MTHRM0IRQ 0x4E12 +#define BXTWC_MTHRM1IRQ 0x4E13 +#define BXTWC_MTHRM2IRQ 0x4E14 +#define BXTWC_MBCUIRQ 0x4E15 +#define BXTWC_MADCIRQ 0x4E16 +#define BXTWC_MCHGR0IRQ 0x4E17 +#define BXTWC_MCHGR1IRQ 0x4E18 +#define BXTWC_MGPIO0IRQ 0x4E19 +#define BXTWC_MGPIO1IRQ 0x4E1A +#define BXTWC_MCRITIRQ 0x4E1B + +/* Whiskey Cove PMIC share same ACPI ID between different platforms */ +#define BROXTON_PMIC_WC_HRV 4 + +/* Manage in two IRQ chips since mask registers are not consecutive */ +enum bxtwc_irqs { + /* Level 1 */ + BXTWC_PWRBTN_LVL1_IRQ = 0, + BXTWC_TMU_LVL1_IRQ, + BXTWC_THRM_LVL1_IRQ, + BXTWC_BCU_LVL1_IRQ, + BXTWC_ADC_LVL1_IRQ, + BXTWC_CHGR_LVL1_IRQ, + BXTWC_GPIO_LVL1_IRQ, + BXTWC_CRIT_LVL1_IRQ, + + /* Level 2 */ + BXTWC_PWRBTN_IRQ, +}; + +enum bxtwc_irqs_level2 { + /* Level 2 */ + BXTWC_THRM0_IRQ = 0, + BXTWC_THRM1_IRQ, + BXTWC_THRM2_IRQ, + BXTWC_BCU_IRQ, + BXTWC_ADC_IRQ, + BXTWC_CHGR0_IRQ, + BXTWC_CHGR1_IRQ, + BXTWC_GPIO0_IRQ, + BXTWC_GPIO1_IRQ, + BXTWC_CRIT_IRQ, +}; + +static const struct regmap_irq bxtwc_regmap_irqs[] = { + REGMAP_IRQ_REG(BXTWC_PWRBTN_LVL1_IRQ, 0, BIT(0)), + REGMAP_IRQ_REG(BXTWC_TMU_LVL1_IRQ, 0, BIT(1)), + REGMAP_IRQ_REG(BXTWC_THRM_LVL1_IRQ, 0, BIT(2)), + REGMAP_IRQ_REG(BXTWC_BCU_LVL1_IRQ, 0, BIT(3)), + REGMAP_IRQ_REG(BXTWC_ADC_LVL1_IRQ, 0, BIT(4)), + REGMAP_IRQ_REG(BXTWC_CHGR_LVL1_IRQ, 0, BIT(5)), + REGMAP_IRQ_REG(BXTWC_GPIO_LVL1_IRQ, 0, BIT(6)), + REGMAP_IRQ_REG(BXTWC_CRIT_LVL1_IRQ, 0, BIT(7)), + REGMAP_IRQ_REG(BXTWC_PWRBTN_IRQ, 1, 0x03), +}; + +static const struct regmap_irq bxtwc_regmap_irqs_level2[] = { + REGMAP_IRQ_REG(BXTWC_THRM0_IRQ, 0, 0xff), + REGMAP_IRQ_REG(BXTWC_THRM1_IRQ, 1, 0xbf), + REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff), + REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f), + REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff), + REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f), + REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f), + REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff), + REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f), + REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03), +}; + +static struct regmap_irq_chip bxtwc_regmap_irq_chip = { + .name = "bxtwc_irq_chip", + .status_base = BXTWC_IRQLVL1, + .mask_base = BXTWC_MIRQLVL1, + .irqs = bxtwc_regmap_irqs, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs), + .num_regs = 2, +}; + +static struct regmap_irq_chip bxtwc_regmap_irq_chip_level2 = { + .name = "bxtwc_irq_chip_level2", + .status_base = BXTWC_THRM0IRQ, + .mask_base = BXTWC_MTHRM0IRQ, + .irqs = bxtwc_regmap_irqs_level2, + .num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_level2), + .num_regs = 10, +}; + +static struct resource gpio_resources[] = { + DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"), + DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"), +}; + +static struct resource adc_resources[] = { + DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"), +}; + +static struct resource charger_resources[] = { + DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"), + DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"), +}; + +static struct resource thermal_resources[] = { + DEFINE_RES_IRQ(BXTWC_THRM0_IRQ), + DEFINE_RES_IRQ(BXTWC_THRM1_IRQ), + DEFINE_RES_IRQ(BXTWC_THRM2_IRQ), +}; + +static struct resource bcu_resources[] = { + DEFINE_RES_IRQ_NAMED(BXTWC_BCU_IRQ, "BCU"), +}; + +static struct mfd_cell bxt_wc_dev[] = { + { + .name = "bxt_wcove_gpadc", + .num_resources = ARRAY_SIZE(adc_resources), + .resources = adc_resources, + }, + { + .name = "bxt_wcove_thermal", + .num_resources = ARRAY_SIZE(thermal_resources), + .resources = thermal_resources, + }, + { + .name = "bxt_wcove_ext_charger", + .num_resources = ARRAY_SIZE(charger_resources), + .resources = charger_resources, + }, + { + .name = "bxt_wcove_bcu", + .num_resources = ARRAY_SIZE(bcu_resources), + .resources = bcu_resources, + }, + { + .name = "bxt_wcove_gpio", + .num_resources = ARRAY_SIZE(gpio_resources), + .resources = gpio_resources, + }, + { + .name = "bxt_wcove_region", + }, +}; + +static int regmap_ipc_byte_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + int ret; + int i2c_addr; + u8 ipc_in[2]; + u8 ipc_out[4]; + struct intel_soc_pmic *pmic = context; + + if (reg & REG_ADDR_MASK) + i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT; + else { + i2c_addr = BXTWC_DEVICE1_ADDR; + if (!i2c_addr) { + dev_err(pmic->dev, "I2C address not set\n"); + return -EINVAL; + } + } + reg &= REG_OFFSET_MASK; + + ipc_in[0] = reg; + ipc_in[1] = i2c_addr; + ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS, + PMC_IPC_PMIC_ACCESS_READ, + ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1); + if (ret) { + dev_err(pmic->dev, "Failed to read from PMIC\n"); + return ret; + } + *val = ipc_out[0]; + + return 0; +} + +static int regmap_ipc_byte_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + int ret; + int i2c_addr; + u8 ipc_in[3]; + struct intel_soc_pmic *pmic = context; + + if (reg & REG_ADDR_MASK) + i2c_addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT; + else { + i2c_addr = BXTWC_DEVICE1_ADDR; + if (!i2c_addr) { + dev_err(pmic->dev, "I2C address not set\n"); + return -EINVAL; + } + } + reg &= REG_OFFSET_MASK; + + ipc_in[0] = reg; + ipc_in[1] = i2c_addr; + ipc_in[2] = val; + ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS, + PMC_IPC_PMIC_ACCESS_WRITE, + ipc_in, sizeof(ipc_in), NULL, 0); + if (ret) { + dev_err(pmic->dev, "Failed to write to PMIC\n"); + return ret; + } + + return 0; +} + +/* sysfs interfaces to r/w PMIC registers, required by initial script */ +static unsigned long bxtwc_reg_addr; +static ssize_t bxtwc_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "0x%lx\n", bxtwc_reg_addr); +} + +static ssize_t bxtwc_reg_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (kstrtoul(buf, 0, &bxtwc_reg_addr)) { + dev_err(dev, "Invalid register address\n"); + return -EINVAL; + } + return (ssize_t)count; +} + +static ssize_t bxtwc_val_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + unsigned int val; + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + ret = regmap_read(pmic->regmap, bxtwc_reg_addr, &val); + if (ret < 0) { + dev_err(dev, "Failed to read 0x%lx\n", bxtwc_reg_addr); + return -EIO; + } + + return sprintf(buf, "0x%02x\n", val); +} + +static ssize_t bxtwc_val_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + if (kstrtoul(buf, 0, (unsigned long *)&val)) { + dev_err(dev, "Invalid register value\n"); + return -EINVAL; + } + + ret = regmap_write(pmic->regmap, bxtwc_reg_addr, val); + if (ret) { + dev_err(dev, "Failed to write value 0x%02x to address 0x%lx", + val, bxtwc_reg_addr); + return -EIO; + } + return count; +} + +static DEVICE_ATTR(addr, S_IWUSR | S_IRUSR, bxtwc_reg_show, bxtwc_reg_store); +static DEVICE_ATTR(val, S_IWUSR | S_IRUSR, bxtwc_val_show, bxtwc_val_store); +static struct attribute *bxtwc_attrs[] = { + &dev_attr_addr.attr, + &dev_attr_val.attr, + NULL +}; + +static const struct attribute_group bxtwc_group = { + .attrs = bxtwc_attrs, +}; + +static const struct regmap_config bxtwc_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .reg_write = regmap_ipc_byte_reg_write, + .reg_read = regmap_ipc_byte_reg_read, +}; + +static int bxtwc_probe(struct platform_device *pdev) +{ + int ret; + acpi_handle handle; + acpi_status status; + unsigned long long hrv; + struct intel_soc_pmic *pmic; + + handle = ACPI_HANDLE(&pdev->dev); + status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv); + if (ACPI_FAILURE(status)) { + dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n"); + return -ENODEV; + } + if (hrv != BROXTON_PMIC_WC_HRV) { + dev_err(&pdev->dev, "Invalid PMIC hardware revision: %llu\n", + hrv); + return -ENODEV; + } + + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + dev_err(&pdev->dev, "Invalid IRQ\n"); + return ret; + } + pmic->irq = ret; + + dev_set_drvdata(&pdev->dev, pmic); + pmic->dev = &pdev->dev; + + pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic, + &bxtwc_regmap_config); + if (IS_ERR(pmic->regmap)) { + ret = PTR_ERR(pmic->regmap); + dev_err(&pdev->dev, "Failed to initialise regmap: %d\n", ret); + return ret; + } + + ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, + IRQF_ONESHOT | IRQF_SHARED, + 0, &bxtwc_regmap_irq_chip, + &pmic->irq_chip_data); + if (ret) { + dev_err(&pdev->dev, "Failed to add IRQ chip\n"); + return ret; + } + + ret = regmap_add_irq_chip(pmic->regmap, pmic->irq, + IRQF_ONESHOT | IRQF_SHARED, + 0, &bxtwc_regmap_irq_chip_level2, + &pmic->irq_chip_data_level2); + if (ret) { + dev_err(&pdev->dev, "Failed to add secondary IRQ chip\n"); + goto err_irq_chip_level2; + } + + ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev, + ARRAY_SIZE(bxt_wc_dev), NULL, 0, + NULL); + if (ret) { + dev_err(&pdev->dev, "Failed to add devices\n"); + goto err_mfd; + } + + ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group); + if (ret) { + dev_err(&pdev->dev, "Failed to create sysfs group %d\n", ret); + goto err_sysfs; + } + + return 0; + +err_sysfs: + mfd_remove_devices(&pdev->dev); +err_mfd: + regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2); +err_irq_chip_level2: + regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); + + return ret; +} + +static int bxtwc_remove(struct platform_device *pdev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev); + + sysfs_remove_group(&pdev->dev.kobj, &bxtwc_group); + mfd_remove_devices(&pdev->dev); + regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); + regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2); + + return 0; +} + +static void bxtwc_shutdown(struct platform_device *pdev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(&pdev->dev); + + disable_irq(pmic->irq); +} + +#ifdef CONFIG_PM_SLEEP +static int bxtwc_suspend(struct device *dev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + disable_irq(pmic->irq); + + return 0; +} + +static int bxtwc_resume(struct device *dev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + + enable_irq(pmic->irq); + return 0; +} +#endif +static SIMPLE_DEV_PM_OPS(bxtwc_pm_ops, bxtwc_suspend, bxtwc_resume); + +static const struct acpi_device_id bxtwc_acpi_ids[] = { + { "INT34D3", }, + { } +}; +MODULE_DEVICE_TABLE(acpi, pmic_acpi_ids); + +static struct platform_driver bxtwc_driver = { + .probe = bxtwc_probe, + .remove = bxtwc_remove, + .shutdown = bxtwc_shutdown, + .driver = { + .name = "BXTWC PMIC", + .pm = &bxtwc_pm_ops, + .acpi_match_table = ACPI_PTR(bxtwc_acpi_ids), + }, +}; + +module_platform_driver(bxtwc_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Qipeng Zha"); diff --git a/include/linux/mfd/intel_bxtwc.h b/include/linux/mfd/intel_bxtwc.h new file mode 100644 index 000000000000..1a0ee9d6efe9 --- /dev/null +++ b/include/linux/mfd/intel_bxtwc.h @@ -0,0 +1,69 @@ +/* + * intel_bxtwc.h - Header file for Intel Broxton Whiskey Cove PMIC + * + * Copyright (C) 2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include + +#ifndef __INTEL_BXTWC_H__ +#define __INTEL_BXTWC_H__ + +/* BXT WC devices */ +#define BXTWC_DEVICE1_ADDR 0x4E +#define BXTWC_DEVICE2_ADDR 0x4F +#define BXTWC_DEVICE3_ADDR 0x5E + +/* device1 Registers */ +#define BXTWC_CHIPID 0x4E00 +#define BXTWC_CHIPVER 0x4E01 + +#define BXTWC_SCHGRIRQ0_ADDR 0x5E1A +#define BXTWC_CHGRCTRL0_ADDR 0x5E16 +#define BXTWC_CHGRCTRL1_ADDR 0x5E17 +#define BXTWC_CHGRCTRL2_ADDR 0x5E18 +#define BXTWC_CHGRSTATUS_ADDR 0x5E19 +#define BXTWC_THRMBATZONE_ADDR 0x4F22 + +#define BXTWC_USBPATH_ADDR 0x5E19 +#define BXTWC_USBPHYCTRL_ADDR 0x5E07 +#define BXTWC_USBIDCTRL_ADDR 0x5E05 +#define BXTWC_USBIDEN_MASK 0x01 +#define BXTWC_USBIDSTAT_ADDR 0x00FF +#define BXTWC_USBSRCDETSTATUS_ADDR 0x5E29 + +#define BXTWC_DBGUSBBC1_ADDR 0x5FE0 +#define BXTWC_DBGUSBBC2_ADDR 0x5FE1 +#define BXTWC_DBGUSBBCSTAT_ADDR 0x5FE2 + +#define BXTWC_WAKESRC_ADDR 0x4E22 +#define BXTWC_WAKESRC2_ADDR 0x4EE5 +#define BXTWC_CHRTTADDR_ADDR 0x5E22 +#define BXTWC_CHRTTDATA_ADDR 0x5E23 + +#define BXTWC_STHRMIRQ0_ADDR 0x4F19 +#define WC_MTHRMIRQ1_ADDR 0x4E12 +#define WC_STHRMIRQ1_ADDR 0x4F1A +#define WC_STHRMIRQ2_ADDR 0x4F1B + +#define BXTWC_THRMZN0H_ADDR 0x4F44 +#define BXTWC_THRMZN0L_ADDR 0x4F45 +#define BXTWC_THRMZN1H_ADDR 0x4F46 +#define BXTWC_THRMZN1L_ADDR 0x4F47 +#define BXTWC_THRMZN2H_ADDR 0x4F48 +#define BXTWC_THRMZN2L_ADDR 0x4F49 +#define BXTWC_THRMZN3H_ADDR 0x4F4A +#define BXTWC_THRMZN3L_ADDR 0x4F4B +#define BXTWC_THRMZN4H_ADDR 0x4F4C +#define BXTWC_THRMZN4L_ADDR 0x4F4D + +#endif -- cgit v1.2.3 From 3dab794f50451fa910d6a8d4d002c4ecda3cc1f5 Mon Sep 17 00:00:00 2001 From: Aaron Sierra Date: Tue, 22 Sep 2015 19:04:24 -0500 Subject: mfd: lpc_ich: Separate device cells for clarity The lpc_ich_cells array gives the wrong impression about the relationship between the watchdog and GPIO devices. They are completely distinct devices, so this patch separates the array into distinct mfd_cell structs per device. A side effect of removing the array, is that the lpc_cells enum is no longer needed. Signed-off-by: Aaron Sierra Acked-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/lpc_ich.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index c5a9a08b5dfb..b514f3cf140d 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -132,24 +132,18 @@ static struct resource gpio_ich_res[] = { }, }; -enum lpc_cells { - LPC_WDT = 0, - LPC_GPIO, +static struct mfd_cell lpc_ich_wdt_cell = { + .name = "iTCO_wdt", + .num_resources = ARRAY_SIZE(wdt_ich_res), + .resources = wdt_ich_res, + .ignore_resource_conflicts = true, }; -static struct mfd_cell lpc_ich_cells[] = { - [LPC_WDT] = { - .name = "iTCO_wdt", - .num_resources = ARRAY_SIZE(wdt_ich_res), - .resources = wdt_ich_res, - .ignore_resource_conflicts = true, - }, - [LPC_GPIO] = { - .name = "gpio_ich", - .num_resources = ARRAY_SIZE(gpio_ich_res), - .resources = gpio_ich_res, - .ignore_resource_conflicts = true, - }, +static struct mfd_cell lpc_ich_gpio_cell = { + .name = "gpio_ich", + .num_resources = ARRAY_SIZE(gpio_ich_res), + .resources = gpio_ich_res, + .ignore_resource_conflicts = true, }; /* chipset related info */ @@ -841,7 +835,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) struct itco_wdt_platform_data *pdata; struct lpc_ich_priv *priv = pci_get_drvdata(dev); struct lpc_ich_info *info; - struct mfd_cell *cell = &lpc_ich_cells[LPC_WDT]; + struct mfd_cell *cell = &lpc_ich_wdt_cell; pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -860,7 +854,7 @@ static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev) { struct lpc_ich_priv *priv = pci_get_drvdata(dev); - struct mfd_cell *cell = &lpc_ich_cells[LPC_GPIO]; + struct mfd_cell *cell = &lpc_ich_gpio_cell; cell->platform_data = &lpc_chipset_info[priv->chipset]; cell->pdata_size = sizeof(struct lpc_ich_info); @@ -904,7 +898,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) base_addr = base_addr_cfg & 0x0000ff80; if (!base_addr) { dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); - lpc_ich_cells[LPC_GPIO].num_resources--; + lpc_ich_gpio_cell.num_resources--; goto gpe0_done; } @@ -918,7 +912,7 @@ static int lpc_ich_init_gpio(struct pci_dev *dev) * the platform_device subsystem doesn't see this resource * or it will register an invalid region. */ - lpc_ich_cells[LPC_GPIO].num_resources--; + lpc_ich_gpio_cell.num_resources--; acpi_conflict = true; } else { lpc_ich_enable_acpi_space(dev); @@ -958,12 +952,12 @@ gpe0_done: lpc_ich_finalize_gpio_cell(dev); ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, - &lpc_ich_cells[LPC_GPIO], 1, NULL, 0, NULL); + &lpc_ich_gpio_cell, 1, NULL, 0, NULL); gpio_done: if (acpi_conflict) pr_warn("Resource conflict(s) found affecting %s\n", - lpc_ich_cells[LPC_GPIO].name); + lpc_ich_gpio_cell.name); return ret; } @@ -1007,7 +1001,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) */ if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { /* Don't register iomem for TCO ver 1 */ - lpc_ich_cells[LPC_WDT].num_resources--; + lpc_ich_wdt_cell.num_resources--; } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) { pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); base_addr = base_addr_cfg & 0xffffc000; @@ -1035,7 +1029,7 @@ static int lpc_ich_init_wdt(struct pci_dev *dev) goto wdt_done; ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, - &lpc_ich_cells[LPC_WDT], 1, NULL, 0, NULL); + &lpc_ich_wdt_cell, 1, NULL, 0, NULL); wdt_done: return ret; -- cgit v1.2.3 From 79ae6bb15945f9b7f3e91db3d68f1b77c4b1451c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 25 Sep 2015 17:31:12 +0100 Subject: platform: x86: PMC IPC depends on ACPI This patch solves: on x86_64: when CONFIG_ACPI is not enabled: ../drivers/mfd/intel_soc_pmic_bxtwc.c: In function 'bxtwc_probe': ../drivers/mfd/intel_soc_pmic_bxtwc.c:342:2: error: implicit declaration of function 'acpi_evaluate_integer' [-Werror=implicit-function-declaration] status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv); ^ Reported-by: Randy Dunlap Signed-off-by: Lee Jones --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index c69bb703f483..744cb80fccbc 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -914,6 +914,7 @@ config PVPANIC config INTEL_PMC_IPC tristate "Intel PMC IPC Driver" + depends on ACPI ---help--- This driver provides support for PMC control on some Intel platforms. The PMC is an ARC processor which defines IPC commands for communication -- cgit v1.2.3 From ced7e09355cd7f4434eb2c34c4fae450c2fee0e7 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 25 Sep 2015 13:39:13 +0100 Subject: mfd: qcom_rpm: Drop use of IRQF_NO_SUSPEND flag The driver handles wakeup irq correctly using irq_set_irq_wake. There's no need to use IRQF_NO_SUSPEND while registering the interrupt. This patch removes the use of IRQF_NO_SUSPEND flag. Signed-off-by: Sudeep Holla Signed-off-by: Lee Jones --- drivers/mfd/qcom_rpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 6afc9fabd94c..207a3bd68559 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c @@ -550,7 +550,7 @@ static int qcom_rpm_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq_ack, qcom_rpm_ack_interrupt, - IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, + IRQF_TRIGGER_RISING, "qcom_rpm_ack", rpm); if (ret) { -- cgit v1.2.3 From ea50e9d3c44b3830eb25286fda5d9f83a68141cf Mon Sep 17 00:00:00 2001 From: Grigoryev Denis Date: Fri, 25 Sep 2015 16:57:09 +0000 Subject: mfd: tps6105x: Fix possible NULL pointer access tps6105 driver provides two cells. One is for GPIO and another one is for selected mode depending on platform data. When tps6105x is used in GPIO-only mode, this driver calls mfd_add_devices() with mfd_cell .name == NULL. This value causes an oops in platform_device_register() later. The following patch adds a mfd_cell for each possible mode thereby excluding .name assignment in runtime. Signed-off-by: Denis Grigoryev Signed-off-by: Lee Jones --- drivers/mfd/tps6105x.c | 72 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index 4a174cdb50b6..51c54951c220 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -64,27 +64,47 @@ static int tps6105x_startup(struct tps6105x *tps6105x) } /* - * MFD cells - we have one cell which is selected operation - * mode, and we always have a GPIO cell. + * MFD cells - we always have a GPIO cell and we have one cell + * which is selected operation mode. */ -static struct mfd_cell tps6105x_cells[] = { - { - /* name will be runtime assigned */ - .id = -1, - }, - { - .name = "tps6105x-gpio", - .id = -1, - }, +static struct mfd_cell tps6105x_gpio_cell = { + .name = "tps6105x-gpio", +}; + +static struct mfd_cell tps6105x_leds_cell = { + .name = "tps6105x-leds", +}; + +static struct mfd_cell tps6105x_flash_cell = { + .name = "tps6105x-flash", }; +static struct mfd_cell tps6105x_regulator_cell = { + .name = "tps6105x-regulator", +}; + +static int tps6105x_add_device(struct tps6105x *tps6105x, + struct mfd_cell *cell) +{ + cell->platform_data = tps6105x; + cell->pdata_size = sizeof(*tps6105x); + + return mfd_add_devices(&tps6105x->client->dev, + PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL); +} + static int tps6105x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tps6105x *tps6105x; struct tps6105x_platform_data *pdata; int ret; - int i; + + pdata = dev_get_platdata(&client->dev); + if (!pdata) { + dev_err(&client->dev, "missing platform data\n"); + return -ENODEV; + } tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL); if (!tps6105x) @@ -96,7 +116,6 @@ static int tps6105x_probe(struct i2c_client *client, i2c_set_clientdata(client, tps6105x); tps6105x->client = client; - pdata = dev_get_platdata(&client->dev); tps6105x->pdata = pdata; ret = tps6105x_startup(tps6105x); @@ -105,38 +124,33 @@ static int tps6105x_probe(struct i2c_client *client, return ret; } - /* Remove warning texts when you implement new cell drivers */ + ret = tps6105x_add_device(tps6105x, &tps6105x_gpio_cell); + if (ret) + return ret; + switch (pdata->mode) { case TPS6105X_MODE_SHUTDOWN: dev_info(&client->dev, "present, not used for anything, only GPIO\n"); break; case TPS6105X_MODE_TORCH: - tps6105x_cells[0].name = "tps6105x-leds"; - dev_warn(&client->dev, - "torch mode is unsupported\n"); + ret = tps6105x_add_device(tps6105x, &tps6105x_leds_cell); break; case TPS6105X_MODE_TORCH_FLASH: - tps6105x_cells[0].name = "tps6105x-flash"; - dev_warn(&client->dev, - "flash mode is unsupported\n"); + ret = tps6105x_add_device(tps6105x, &tps6105x_flash_cell); break; case TPS6105X_MODE_VOLTAGE: - tps6105x_cells[0].name ="tps6105x-regulator"; + ret = tps6105x_add_device(tps6105x, &tps6105x_regulator_cell); break; default: + dev_warn(&client->dev, "invalid mode: %d\n", pdata->mode); break; } - /* Set up and register the platform devices. */ - for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) { - /* One state holder for all drivers, this is simple */ - tps6105x_cells[i].platform_data = tps6105x; - tps6105x_cells[i].pdata_size = sizeof(*tps6105x); - } + if (ret) + mfd_remove_devices(&client->dev); - return mfd_add_devices(&client->dev, 0, tps6105x_cells, - ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL); + return ret; } static int tps6105x_remove(struct i2c_client *client) -- cgit v1.2.3 From a48baac52aab9b017fb79f27795e69193e0f1d24 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:01 +0200 Subject: mfd: htc-i2cpld: Remove unneded ret variable The ret variable is not needed since is not used in the function. Remove the variable and just return 0 instead. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/htc-i2cpld.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index 1bd5b042c8b3..0c6ff727b2ec 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -318,7 +318,6 @@ static int htcpld_setup_chip_irq( struct htcpld_data *htcpld; struct htcpld_chip *chip; unsigned int irq, irq_end; - int ret = 0; /* Get the platform and driver data */ htcpld = platform_get_drvdata(pdev); @@ -333,7 +332,7 @@ static int htcpld_setup_chip_irq( irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); } - return ret; + return 0; } static int htcpld_register_chip_i2c( -- cgit v1.2.3 From a260fba1158241d168bf14eb7cd1176b29ad263c Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:02 +0200 Subject: mfd: arizona: Remove unneded ret variable The ret variable is not needed since is not used in the function. Remove the variable and just return 0 instead. Signed-off-by: Javier Martinez Canillas Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 44cfdbb295db..acf354875338 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -69,8 +69,6 @@ EXPORT_SYMBOL_GPL(arizona_clk32k_enable); int arizona_clk32k_disable(struct arizona *arizona) { - int ret = 0; - mutex_lock(&arizona->clk_lock); BUG_ON(arizona->clk32k_ref <= 0); @@ -90,7 +88,7 @@ int arizona_clk32k_disable(struct arizona *arizona) mutex_unlock(&arizona->clk_lock); - return ret; + return 0; } EXPORT_SYMBOL_GPL(arizona_clk32k_disable); -- cgit v1.2.3 From e7238fd2554ebfbc2611ae5c7e58d4cd76f276dc Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:03 +0200 Subject: mfd: pcf50633: Remove unneded ret variable The ret variable is not needed since is not used in the function. Remove the variable and just return 0 instead. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/pcf50633-irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/pcf50633-irq.c b/drivers/mfd/pcf50633-irq.c index 498286cbb530..71d43edf110c 100644 --- a/drivers/mfd/pcf50633-irq.c +++ b/drivers/mfd/pcf50633-irq.c @@ -55,7 +55,7 @@ EXPORT_SYMBOL_GPL(pcf50633_free_irq); static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask) { u8 reg, bit; - int ret = 0, idx; + int idx; idx = irq >> 3; reg = PCF50633_REG_INT1M + idx; @@ -72,7 +72,7 @@ static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask) mutex_unlock(&pcf->lock); - return ret; + return 0; } int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) -- cgit v1.2.3 From d8498df1e40e5a232ebe1f1b33edb34887f6a037 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:04 +0200 Subject: mfd: kempld-core: Simplify function return logic The invoked functions already return zero on success or a negative errno code so there is no need to open code the logic in the caller. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/kempld-core.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c index 463f4eae20c1..05b924542ee2 100644 --- a/drivers/mfd/kempld-core.c +++ b/drivers/mfd/kempld-core.c @@ -448,7 +448,6 @@ static int kempld_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct kempld_device_data *pld; struct resource *ioport; - int ret; pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); if (!pld) @@ -471,11 +470,7 @@ static int kempld_probe(struct platform_device *pdev) mutex_init(&pld->lock); platform_set_drvdata(pdev, pld); - ret = kempld_detect_device(pld); - if (ret) - return ret; - - return 0; + return kempld_detect_device(pld); } static int kempld_remove(struct platform_device *pdev) @@ -756,7 +751,6 @@ MODULE_DEVICE_TABLE(dmi, kempld_dmi_table); static int __init kempld_init(void) { const struct dmi_system_id *id; - int ret; if (force_device_id[0]) { for (id = kempld_dmi_table; @@ -771,11 +765,7 @@ static int __init kempld_init(void) return -ENODEV; } - ret = platform_driver_register(&kempld_driver); - if (ret) - return ret; - - return 0; + return platform_driver_register(&kempld_driver); } static void __exit kempld_exit(void) -- cgit v1.2.3 From b158b69a37651b20a0e68f89cf118461e7de4872 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:05 +0200 Subject: mfd: rtsx: Simplify function return logic The invoked functions already return zero on success or a negative errno code so there is no need to open code the logic in the caller. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/rts5209.c | 6 +----- drivers/mfd/rts5227.c | 6 +----- drivers/mfd/rts5229.c | 6 +----- drivers/mfd/rts5249.c | 6 +----- drivers/mfd/rtsx_pcr.c | 6 +----- 5 files changed, 5 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 373e253c33df..b95beecf767f 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c @@ -138,11 +138,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x00); - err = rtsx_pci_send_cmd(pcr, 100); - if (err < 0) - return err; - - return 0; + return rtsx_pci_send_cmd(pcr, 100); } static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index ce012d78ce2a..c5a65298c781 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -179,11 +179,7 @@ static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card) SD_POWER_MASK, SD_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x06); - err = rtsx_pci_send_cmd(pcr, 100); - if (err < 0) - return err; - - return 0; + return rtsx_pci_send_cmd(pcr, 100); } static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card) diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index ace45384ec8b..9ed9dc84eac8 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c @@ -129,11 +129,7 @@ static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card) SD_POWER_MASK, SD_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x06); - err = rtsx_pci_send_cmd(pcr, 100); - if (err < 0) - return err; - - return 0; + return rtsx_pci_send_cmd(pcr, 100); } static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c index eb2d5866f719..40f8bb14fc59 100644 --- a/drivers/mfd/rts5249.c +++ b/drivers/mfd/rts5249.c @@ -234,11 +234,7 @@ static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card) SD_POWER_MASK, SD_VCC_POWER_ON); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0x06); - err = rtsx_pci_send_cmd(pcr, 100); - if (err < 0) - return err; - - return 0; + return rtsx_pci_send_cmd(pcr, 100); } static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card) diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index a66540a49079..b98cf1de0a55 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -571,11 +571,7 @@ static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl) tbl++; } - err = rtsx_pci_send_cmd(pcr, 100); - if (err < 0) - return err; - - return 0; + return rtsx_pci_send_cmd(pcr, 100); } int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card) -- cgit v1.2.3 From 5597da29496317fbcfe4db9f8b65fa8645d4cbed Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:06 +0200 Subject: mfd: da903x: Simplify function return logic The invoked function already returns zero on success or a negative errno code so there is no need to open code the logic in the caller. Signed-off-by: Javier Martinez Canillas Acked-by: Adam Thomson Signed-off-by: Lee Jones --- drivers/mfd/da903x.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index ef7fe2ae2fa4..37e4426ef061 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -532,11 +532,7 @@ static int da903x_probe(struct i2c_client *client, return ret; } - ret = da903x_add_subdevs(chip, pdata); - if (ret) - return ret; - - return 0; + return da903x_add_subdevs(chip, pdata); } static int da903x_remove(struct i2c_client *client) -- cgit v1.2.3 From a1c16d71bceec404573ee4ff712f3dc0e58d31c8 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:08 +0200 Subject: mfd: lm3533: Simplify function return logic The invoked functions already return zero on success or a negative errno code so there is no need to open code the logic in the caller. Signed-off-by: Javier Martinez Canillas Signed-off-by: Lee Jones --- drivers/mfd/lm3533-core.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c index 643f3750e830..193ecee1fa7e 100644 --- a/drivers/mfd/lm3533-core.c +++ b/drivers/mfd/lm3533-core.c @@ -472,11 +472,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533, if (ret) return ret; - ret = lm3533_set_boost_ovp(lm3533, pdata->boost_ovp); - if (ret) - return ret; - - return 0; + return lm3533_set_boost_ovp(lm3533, pdata->boost_ovp); } static int lm3533_device_init(struct lm3533 *lm3533) @@ -613,11 +609,7 @@ static int lm3533_i2c_probe(struct i2c_client *i2c, lm3533->dev = &i2c->dev; lm3533->irq = i2c->irq; - ret = lm3533_device_init(lm3533); - if (ret) - return ret; - - return 0; + return lm3533_device_init(lm3533); } static int lm3533_i2c_remove(struct i2c_client *i2c) -- cgit v1.2.3 From ad698ea425f90e4d09694c2cf7155cad4d7badb3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 29 Sep 2015 13:26:07 +0200 Subject: mfd: da9052: Simplify function return logic The invoked functions already return zero on success or a negative errno code so there is no need to open code the logic in the caller. Signed-off-by: Javier Martinez Canillas Acked-by: Adam Thomson Signed-off-by: Lee Jones --- drivers/mfd/da9052-i2c.c | 6 +----- drivers/mfd/da9052-spi.c | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 02887001e800..2697ffb08009 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -174,11 +174,7 @@ static int da9052_i2c_probe(struct i2c_client *client, return ret; } - ret = da9052_device_init(da9052, id->driver_data); - if (ret != 0) - return ret; - - return 0; + return da9052_device_init(da9052, id->driver_data); } static int da9052_i2c_remove(struct i2c_client *client) diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index b5de8a6856c0..0f5e2c2858c1 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c @@ -56,11 +56,7 @@ static int da9052_spi_probe(struct spi_device *spi) return ret; } - ret = da9052_device_init(da9052, id->driver_data); - if (ret != 0) - return ret; - - return 0; + return da9052_device_init(da9052, id->driver_data); } static int da9052_spi_remove(struct spi_device *spi) -- cgit v1.2.3 From f3a654c5198b1de3e6241ab6a9d5c52295504970 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 28 Sep 2015 12:56:36 +0300 Subject: mfd: intel_soc_pmic_bxtwc: 64 bit bug in bxtwc_val_store() The call to kstrtoul() will corrupt memory on 64 bit systems because an int is 4 bytes and a long is 8. Also it's not a good idea to let users trigger a dev_err() because it just ends up flooding /var/log/messages so I removed the printk. Fixes: 2ddd2086ea9c ('mfd: add Intel Broxton Whiskey Cove PMIC driver') Signed-off-by: Dan Carpenter Signed-off-by: Lee Jones --- drivers/mfd/intel_soc_pmic_bxtwc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c index 40acaff2e1c3..b9428767e615 100644 --- a/drivers/mfd/intel_soc_pmic_bxtwc.c +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c @@ -297,10 +297,9 @@ static ssize_t bxtwc_val_store(struct device *dev, unsigned int val; struct intel_soc_pmic *pmic = dev_get_drvdata(dev); - if (kstrtoul(buf, 0, (unsigned long *)&val)) { - dev_err(dev, "Invalid register value\n"); - return -EINVAL; - } + ret = kstrtouint(buf, 0, &val); + if (ret) + return ret; ret = regmap_write(pmic->regmap, bxtwc_reg_addr, val); if (ret) { -- cgit v1.2.3 From 5c41f11c625e6860b00e58c237dd03a89a8beccc Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Mon, 28 Sep 2015 11:13:26 +0200 Subject: mfd: atmel-flexcom: Add a driver for Atmel Flexible Serial Communication Unit This driver supports the new Atmel Flexcom. The Flexcom is a wrapper which integrates one SPI controller, one I2C controller and one USART. Only one function can be enabled at a time. This driver selects the function once for all, when the Flexcom is probed, according to the value of the new "atmel,flexcom-mode" device tree property. This driver has chosen to present the Flexcom to the system as a MFD so the implementation is seamless for the existing Atmel SPI, I2C and USART drivers. Also the Flexcom embeds FIFOs: the latest patches of the SPI, I2C and USART drivers take advantage of this new feature. Signed-off-by: Cyrille Pitchen Acked-by: Boris Brezillon Acked-by: Alexandre Belloni Acked-by: Nicolas Ferre Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 11 +++++ drivers/mfd/Makefile | 1 + drivers/mfd/atmel-flexcom.c | 104 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 drivers/mfd/atmel-flexcom.c (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 99d63675f073..87e84e7c71da 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -60,6 +60,17 @@ config MFD_AAT2870_CORE additional drivers must be enabled in order to use the functionality of the device. +config MFD_ATMEL_FLEXCOM + tristate "Atmel Flexcom (Flexible Serial Communication Unit)" + select MFD_CORE + depends on OF + help + Select this to get support for Atmel Flexcom. This is a wrapper + which embeds a SPI controller, a I2C controller and a USART. Only + one function can be used at a time. The choice is done at boot time + by the probe function of this MFD driver according to a device tree + property. + config MFD_ATMEL_HLCDC tristate "Atmel HLCDC (High-end LCD Controller)" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index d6c21e3c409f..a8b76b81b467 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -164,6 +164,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o +obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c new file mode 100644 index 000000000000..e8e67be6b493 --- /dev/null +++ b/drivers/mfd/atmel-flexcom.c @@ -0,0 +1,104 @@ +/* + * Driver for Atmel Flexcom + * + * Copyright (C) 2015 Atmel Corporation + * + * Author: Cyrille Pitchen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* I/O register offsets */ +#define FLEX_MR 0x0 /* Mode Register */ +#define FLEX_VERSION 0xfc /* Version Register */ + +/* Mode Register bit fields */ +#define FLEX_MR_OPMODE_OFFSET (0) /* Operating Mode */ +#define FLEX_MR_OPMODE_MASK (0x3 << FLEX_MR_OPMODE_OFFSET) +#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \ + FLEX_MR_OPMODE_MASK) + + +static int atmel_flexcom_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct clk *clk; + struct resource *res; + void __iomem *base; + u32 opmode; + int err; + + err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode); + if (err) + return err; + + if (opmode < ATMEL_FLEXCOM_MODE_USART || + opmode > ATMEL_FLEXCOM_MODE_TWI) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + err = clk_prepare_enable(clk); + if (err) + return err; + + /* + * Set the Operating Mode in the Mode Register: only the selected device + * is clocked. Hence, registers of the other serial devices remain + * inaccessible and are read as zero. Also the external I/O lines of the + * Flexcom are muxed to reach the selected device. + */ + writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR); + + clk_disable_unprepare(clk); + + return of_platform_populate(np, NULL, NULL, &pdev->dev); +} + +static const struct of_device_id atmel_flexcom_of_match[] = { + { .compatible = "atmel,sama5d2-flexcom" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match); + +static struct platform_driver atmel_flexcom_driver = { + .probe = atmel_flexcom_probe, + .driver = { + .name = "atmel_flexcom", + .of_match_table = atmel_flexcom_of_match, + }, +}; + +module_platform_driver(atmel_flexcom_driver); + +MODULE_AUTHOR("Cyrille Pitchen "); +MODULE_DESCRIPTION("Atmel Flexcom MFD driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 0386af30d3d99d942dd68a8c64beb4f03958e74f Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Thu, 8 Oct 2015 16:17:51 +0100 Subject: mfd: da9053: Addition of extra registers for GPIOs 8-13 Definitions for GPIO registers 8, 9, 10, 11, 12 and 13 are added into the register header file. - DA9052_GPIO_8_9_REG 25 - DA9052_GPIO_10_11_REG 26 - DA9052_GPIO_12_13_REG 27 A modification is also made to the MFD core code to define these registers as readable and writable. The functions for da9052_reg_readable() and da9052_reg_writeable() have had their case statements altered to include these new registers. Signed-off-by: Steve Twiss Signed-off-by: Lee Jones --- drivers/mfd/da9052-core.c | 6 ++++++ include/linux/mfd/da9052/reg.h | 3 +++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 46e3840c7a37..c0bf68a3e614 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -51,6 +51,9 @@ static bool da9052_reg_readable(struct device *dev, unsigned int reg) case DA9052_GPIO_2_3_REG: case DA9052_GPIO_4_5_REG: case DA9052_GPIO_6_7_REG: + case DA9052_GPIO_8_9_REG: + case DA9052_GPIO_10_11_REG: + case DA9052_GPIO_12_13_REG: case DA9052_GPIO_14_15_REG: case DA9052_ID_0_1_REG: case DA9052_ID_2_3_REG: @@ -178,6 +181,9 @@ static bool da9052_reg_writeable(struct device *dev, unsigned int reg) case DA9052_GPIO_2_3_REG: case DA9052_GPIO_4_5_REG: case DA9052_GPIO_6_7_REG: + case DA9052_GPIO_8_9_REG: + case DA9052_GPIO_10_11_REG: + case DA9052_GPIO_12_13_REG: case DA9052_GPIO_14_15_REG: case DA9052_ID_0_1_REG: case DA9052_ID_2_3_REG: diff --git a/include/linux/mfd/da9052/reg.h b/include/linux/mfd/da9052/reg.h index c4dd3a8add21..5010f978725c 100644 --- a/include/linux/mfd/da9052/reg.h +++ b/include/linux/mfd/da9052/reg.h @@ -65,6 +65,9 @@ #define DA9052_GPIO_2_3_REG 22 #define DA9052_GPIO_4_5_REG 23 #define DA9052_GPIO_6_7_REG 24 +#define DA9052_GPIO_8_9_REG 25 +#define DA9052_GPIO_10_11_REG 26 +#define DA9052_GPIO_12_13_REG 27 #define DA9052_GPIO_14_15_REG 28 /* POWER SEQUENCER CONTROL REGISTERS */ -- cgit v1.2.3 From 5349ca11ca33dd393539024b613ef352d24cbb51 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Mon, 12 Oct 2015 17:26:07 +0100 Subject: mfd: Kconfig: Compile MFD_STW481X with COMPILE_TEST The driver depends on ARCH_NOMADIK but there isn't a build dependency so it's a good idea to allow the driver to always be built when the COMPILE_TEST option is enabled. That way, the driver can be built with a config generated by make allyesconfig and check if a patch would break the build. Signed-off-by: Luis de Bethencourt Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 87e84e7c71da..d6514fb35f78 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1482,7 +1482,7 @@ config MFD_WM8994 config MFD_STW481X tristate "Support for ST Microelectronics STw481x" - depends on I2C && ARCH_NOMADIK + depends on I2C && (ARCH_NOMADIK || COMPILE_TEST) select REGMAP_I2C select MFD_CORE help -- cgit v1.2.3 From 6f44b14870520e2758b758cc3b3b4c09c4b715ab Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 9 Oct 2015 18:22:03 +0800 Subject: mfd: da9062-core: Rename get_device_type to da9062_get_device_type Rename get_device_type() to da9062_get_device_type(). This function is only used in this file so make it static. Signed-off-by: Axel Lin Signed-off-by: Lee Jones --- drivers/mfd/da9062-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c index f80d9471f2e7..a9ad024ec6b0 100644 --- a/drivers/mfd/da9062-core.c +++ b/drivers/mfd/da9062-core.c @@ -198,7 +198,7 @@ static int da9062_clear_fault_log(struct da9062 *chip) return ret; } -int get_device_type(struct da9062 *chip) +static int da9062_get_device_type(struct da9062 *chip) { int device_id, variant_id, variant_mrc; int ret; @@ -466,7 +466,7 @@ static int da9062_i2c_probe(struct i2c_client *i2c, if (ret < 0) dev_warn(chip->dev, "Cannot clear fault log\n"); - ret = get_device_type(chip); + ret = da9062_get_device_type(chip); if (ret) return ret; -- cgit v1.2.3 From ce6a5acc93876f619f32f8f60c7c6e549e46d962 Mon Sep 17 00:00:00 2001 From: Micky Ching Date: Mon, 29 Jun 2015 09:19:39 +0800 Subject: mfd: rtsx: Add support for rts522A rts522a(rts5227s) is derived from rts5227, and mainly same with rts5227. Add it to file mfd/rts5227.c to support this chip. Signed-off-by: Micky Ching Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 7 ++-- drivers/mfd/rts5227.c | 77 ++++++++++++++++++++++++++++++++++++++++++-- drivers/mfd/rtsx_pcr.c | 5 +++ drivers/mfd/rtsx_pcr.h | 3 ++ include/linux/mfd/rtsx_pci.h | 6 ++++ 5 files changed, 93 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d6514fb35f78..2db1337432cf 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -736,9 +736,10 @@ config MFD_RTSX_PCI select MFD_CORE help This supports for Realtek PCI-Express card reader including rts5209, - rts5229, rtl8411, etc. Realtek card reader supports access to many - types of memory cards, such as Memory Stick, Memory Stick Pro, - Secure Digital and MultiMediaCard. + rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc. + Realtek card reader supports access to many types of memory cards, + such as Memory Stick, Memory Stick Pro, Secure Digital and + MultiMediaCard. config MFD_RT5033 tristate "Richtek RT5033 Power Management IC" diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c index c5a65298c781..ff296a4bf3d2 100644 --- a/drivers/mfd/rts5227.c +++ b/drivers/mfd/rts5227.c @@ -26,6 +26,14 @@ #include "rtsx_pcr.h" +static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr) +{ + u8 val; + + rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val); + return val & 0x0F; +} + static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage) { u8 driving_3v3[4][3] = { @@ -88,7 +96,7 @@ static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); if (pm_state == HOST_ENTER_S3) - rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10); + rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10); rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); } @@ -121,7 +129,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8); else rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88); - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00); return rtsx_pci_send_cmd(pcr, 100); } @@ -294,8 +302,73 @@ void rts5227_init_params(struct rtsx_pcr *pcr) pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15); pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7); + pcr->ic_version = rts5227_get_ic_version(pcr); pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl; pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl; pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl; pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl; + + pcr->reg_pm_ctrl3 = PM_CTRL3; +} + +static int rts522a_optimize_phy(struct rtsx_pcr *pcr) +{ + int err; + + err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN, + 0x00); + if (err < 0) + return err; + + if (is_version(pcr, 0x522A, IC_VER_A)) { + err = rtsx_pci_write_phy_register(pcr, PHY_RCR2, + PHY_RCR2_INIT_27S); + if (err) + return err; + + rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S); + rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S); + rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S); + rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S); + } + + return 0; +} + +static int rts522a_extra_init_hw(struct rtsx_pcr *pcr) +{ + rts5227_extra_init_hw(pcr); + + rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG, + FUNC_FORCE_UPME_XMT_DBG); + rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04); + rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0); + rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11); + + return 0; +} + +/* rts522a operations mainly derived from rts5227, except phy/hw init setting. + */ +static const struct pcr_ops rts522a_pcr_ops = { + .fetch_vendor_settings = rts5227_fetch_vendor_settings, + .extra_init_hw = rts522a_extra_init_hw, + .optimize_phy = rts522a_optimize_phy, + .turn_on_led = rts5227_turn_on_led, + .turn_off_led = rts5227_turn_off_led, + .enable_auto_blink = rts5227_enable_auto_blink, + .disable_auto_blink = rts5227_disable_auto_blink, + .card_power_on = rts5227_card_power_on, + .card_power_off = rts5227_card_power_off, + .switch_output_voltage = rts5227_switch_output_voltage, + .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, + .force_power_down = rts5227_force_power_down, +}; + +void rts522a_init_params(struct rtsx_pcr *pcr) +{ + rts5227_init_params(pcr); + + pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3; } diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index b98cf1de0a55..f3820d08c9a3 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -55,6 +55,7 @@ static const struct pci_device_id rtsx_pci_ids[] = { { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 }, @@ -1098,6 +1099,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) rts5227_init_params(pcr); break; + case 0x522A: + rts522a_init_params(pcr); + break; + case 0x5249: rts5249_init_params(pcr); break; diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index ce48842570d7..931d1ae3ce32 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -27,6 +27,8 @@ #define MIN_DIV_N_PCR 80 #define MAX_DIV_N_PCR 208 +#define RTS522A_PM_CTRL3 0xFF7E + #define RTS524A_PME_FORCE_CTL 0xFF78 #define RTS524A_PM_CTRL3 0xFF7E @@ -38,6 +40,7 @@ void rts5229_init_params(struct rtsx_pcr *pcr); void rtl8411_init_params(struct rtsx_pcr *pcr); void rtl8402_init_params(struct rtsx_pcr *pcr); void rts5227_init_params(struct rtsx_pcr *pcr); +void rts522a_init_params(struct rtsx_pcr *pcr); void rts5249_init_params(struct rtsx_pcr *pcr); void rts524a_init_params(struct rtsx_pcr *pcr); void rts525a_init_params(struct rtsx_pcr *pcr); diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index ff843e7ca23d..7eb7cbac0a9a 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -589,6 +589,7 @@ #define FORCE_ASPM_NO_ASPM 0x00 #define PM_CLK_FORCE_CTL 0xFE58 #define FUNC_FORCE_CTL 0xFE59 +#define FUNC_FORCE_UPME_XMT_DBG 0x02 #define PERST_GLITCH_WIDTH 0xFE5C #define CHANGE_LINK_STATE 0xFE5B #define RESET_LOAD_REG 0xFE5E @@ -712,6 +713,7 @@ #define PHY_RCR1 0x02 #define PHY_RCR1_ADP_TIME_4 0x0400 #define PHY_RCR1_VCO_COARSE 0x001F +#define PHY_RCR1_INIT_27S 0x0A1F #define PHY_SSCCR2 0x02 #define PHY_SSCCR2_PLL_NCODE 0x0A00 #define PHY_SSCCR2_TIME0 0x001C @@ -724,6 +726,7 @@ #define PHY_RCR2_FREQSEL_12 0x0040 #define PHY_RCR2_CDR_SC_12P 0x0010 #define PHY_RCR2_CALIB_LATE 0x0002 +#define PHY_RCR2_INIT_27S 0xC152 #define PHY_SSCCR3 0x03 #define PHY_SSCCR3_STEP_IN 0x2740 #define PHY_SSCCR3_CHECK_DELAY 0x0008 @@ -800,12 +803,14 @@ #define PHY_ANA1A_RXT_BIST 0x0500 #define PHY_ANA1A_TXR_BIST 0x0040 #define PHY_ANA1A_REV 0x0006 +#define PHY_FLD0_INIT_27S 0x2546 #define PHY_FLD1 0x1B #define PHY_FLD2 0x1C #define PHY_FLD3 0x1D #define PHY_FLD3_TIMER_4 0x0800 #define PHY_FLD3_TIMER_6 0x0020 #define PHY_FLD3_RXDELINK 0x0004 +#define PHY_FLD3_INIT_27S 0x0004 #define PHY_ANA1D 0x1D #define PHY_ANA1D_DEBUG_ADDR 0x0004 #define _PHY_FLD0 0x1D @@ -824,6 +829,7 @@ #define PHY_FLD4_BER_COUNT 0x00E0 #define PHY_FLD4_BER_TIMER 0x000A #define PHY_FLD4_BER_CHK_EN 0x0001 +#define PHY_FLD4_INIT_27S 0x5C7F #define PHY_DIG1E 0x1E #define PHY_DIG1E_REV 0x4000 #define PHY_DIG1E_D0_X_D1 0x1000 -- cgit v1.2.3 From 0a27186448f17cb1b6734bb302cc1299008e91e9 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Wed, 7 Oct 2015 17:58:48 +0530 Subject: mfd: lm3533: Fix unused variable build warning We were getting build warning about unused variable 'ret'. The commit c749db571dcf has removed the use of ret but missed removing the variable which is unused now. Fixes: c749db571dcf ("mfd: lm3533: Simplify function return logic") Signed-off-by: Sudip Mukherjee Signed-off-by: Lee Jones --- drivers/mfd/lm3533-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c index 193ecee1fa7e..5abcbb2e8849 100644 --- a/drivers/mfd/lm3533-core.c +++ b/drivers/mfd/lm3533-core.c @@ -592,7 +592,6 @@ static int lm3533_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct lm3533 *lm3533; - int ret; dev_dbg(&i2c->dev, "%s\n", __func__); -- cgit v1.2.3 From 18eb3f041addcdf8ef4a4b80547a67557c8826d6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 7 Oct 2015 09:18:04 +0800 Subject: mfd: Make TPS6105X select REGMAP_I2C This is required since commit 7e5071199355 ("mfd: tps6105x: Use i2c regmap to access registers"). Signed-off-by: Axel Lin Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 2db1337432cf..4d92df6ef9fe 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1071,6 +1071,7 @@ config MFD_PALMAS config TPS6105X tristate "TI TPS61050/61052 Boost Converters" depends on I2C + select REGMAP_I2C select REGULATOR select MFD_CORE select REGULATOR_FIXED_VOLTAGE -- cgit v1.2.3 From e7811147aafb3d6364b8d60223cbe6c323cdf725 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 2 Oct 2015 13:29:10 +0100 Subject: mfd: arizona: Factor out DCVDD isolation control Currently DCVDD isolation is enabled and disabled for runtime_suspend and runtime_resume. Future codecs will not have the isolation control so to prepare for these codecs this patch factors out the isolation control allowing it to be called as needed in the existing codec-specific switch cases. Signed-off-by: Richard Fitzgerald Acked-by: Lee Jones Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 108 ++++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index acf354875338..29be2628352c 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -460,6 +460,33 @@ static int wm5102_clear_write_sequencer(struct arizona *arizona) } #ifdef CONFIG_PM +static int arizona_isolate_dcvdd(struct arizona *arizona) +{ + int ret; + + ret = regmap_update_bits(arizona->regmap, + ARIZONA_ISOLATION_CONTROL, + ARIZONA_ISOLATE_DCVDD1, + ARIZONA_ISOLATE_DCVDD1); + if (ret != 0) + dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", ret); + + return ret; +} + +static int arizona_connect_dcvdd(struct arizona *arizona) +{ + int ret; + + ret = regmap_update_bits(arizona->regmap, + ARIZONA_ISOLATION_CONTROL, + ARIZONA_ISOLATE_DCVDD1, 0); + if (ret != 0) + dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret); + + return ret; +} + static int arizona_runtime_resume(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); @@ -499,14 +526,9 @@ static int arizona_runtime_resume(struct device *dev) switch (arizona->type) { case WM5102: if (arizona->external_dcvdd) { - ret = regmap_update_bits(arizona->regmap, - ARIZONA_ISOLATION_CONTROL, - ARIZONA_ISOLATE_DCVDD1, 0); - if (ret != 0) { - dev_err(arizona->dev, - "Failed to connect DCVDD: %d\n", ret); + ret = arizona_connect_dcvdd(arizona); + if (ret != 0) goto err; - } } ret = wm5102_patch(arizona); @@ -531,14 +553,9 @@ static int arizona_runtime_resume(struct device *dev) goto err; if (arizona->external_dcvdd) { - ret = regmap_update_bits(arizona->regmap, - ARIZONA_ISOLATION_CONTROL, - ARIZONA_ISOLATE_DCVDD1, 0); - if (ret) { - dev_err(arizona->dev, - "Failed to connect DCVDD: %d\n", ret); + ret = arizona_connect_dcvdd(arizona); + if (ret != 0) goto err; - } } else { /* * As this is only called for the internal regulator @@ -569,14 +586,9 @@ static int arizona_runtime_resume(struct device *dev) goto err; if (arizona->external_dcvdd) { - ret = regmap_update_bits(arizona->regmap, - ARIZONA_ISOLATION_CONTROL, - ARIZONA_ISOLATE_DCVDD1, 0); - if (ret != 0) { - dev_err(arizona->dev, - "Failed to connect DCVDD: %d\n", ret); + ret = arizona_connect_dcvdd(arizona); + if (ret != 0) goto err; - } } break; } @@ -609,37 +621,36 @@ static int arizona_runtime_suspend(struct device *dev) return ret; } - if (arizona->external_dcvdd) { - ret = regmap_update_bits(arizona->regmap, - ARIZONA_ISOLATION_CONTROL, - ARIZONA_ISOLATE_DCVDD1, - ARIZONA_ISOLATE_DCVDD1); - if (ret != 0) { - dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", - ret); - return ret; - } - } - switch (arizona->type) { case WM5110: case WM8280: - if (arizona->external_dcvdd) - break; - - /* - * As this is only called for the internal regulator - * (where we know voltage ranges available) it is ok - * to request an exact range. - */ - ret = regulator_set_voltage(arizona->dcvdd, 1175000, 1175000); - if (ret < 0) { - dev_err(arizona->dev, - "Failed to set suspend voltage: %d\n", ret); - return ret; + if (arizona->external_dcvdd) { + ret = arizona_isolate_dcvdd(arizona); + if (ret != 0) + return ret; + } else { + /* + * As this is only called for the internal regulator + * (where we know voltage ranges available) it is ok + * to request an exact range. + */ + ret = regulator_set_voltage(arizona->dcvdd, + 1175000, 1175000); + if (ret < 0) { + dev_err(arizona->dev, + "Failed to set suspend voltage: %d\n", + ret); + return ret; + } } break; case WM5102: + if (arizona->external_dcvdd) { + ret = arizona_isolate_dcvdd(arizona); + if (ret != 0) + return ret; + } + if (!(val & ARIZONA_JD1_ENA)) { ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0); @@ -652,6 +663,11 @@ static int arizona_runtime_suspend(struct device *dev) } break; default: + if (arizona->external_dcvdd) { + ret = arizona_isolate_dcvdd(arizona); + if (ret != 0) + return ret; + } break; } -- cgit v1.2.3 From e3424273545bef85ebf959c90091d60ba3fc2efc Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 2 Oct 2015 13:29:11 +0100 Subject: mfd: arizona: Factor out checking of jack detection state Currently runtime_suspend will fully power off the codec if the jack detection is not enabled. Not all future codecs will have jack detection so to prepare for these codecs this patch factors out the check so that it be called as needed in the existing codec-specific switch cases. Signed-off-by: Richard Fitzgerald Acked-by: Lee Jones Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 29be2628352c..e32d0d30e9cd 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -487,6 +487,23 @@ static int arizona_connect_dcvdd(struct arizona *arizona) return ret; } +static int arizona_is_jack_det_active(struct arizona *arizona) +{ + unsigned int val; + int ret; + + ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val); + if (ret) { + dev_err(arizona->dev, + "Failed to check jack det status: %d\n", ret); + return ret; + } else if (val & ARIZONA_JD1_ENA) { + return 1; + } else { + return 0; + } +} + static int arizona_runtime_resume(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); @@ -610,20 +627,18 @@ err: static int arizona_runtime_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); - unsigned int val; + unsigned int jd_active = 0; int ret; dev_dbg(arizona->dev, "Entering AoD mode\n"); - ret = regmap_read(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, &val); - if (ret) { - dev_err(dev, "Failed to check jack det status: %d\n", ret); - return ret; - } - switch (arizona->type) { case WM5110: case WM8280: + jd_active = arizona_is_jack_det_active(arizona); + if (jd_active < 0) + return jd_active; + if (arizona->external_dcvdd) { ret = arizona_isolate_dcvdd(arizona); if (ret != 0) @@ -645,13 +660,17 @@ static int arizona_runtime_suspend(struct device *dev) } break; case WM5102: + jd_active = arizona_is_jack_det_active(arizona); + if (jd_active < 0) + return jd_active; + if (arizona->external_dcvdd) { ret = arizona_isolate_dcvdd(arizona); if (ret != 0) return ret; } - if (!(val & ARIZONA_JD1_ENA)) { + if (!jd_active) { ret = regmap_write(arizona->regmap, ARIZONA_WRITE_SEQUENCER_CTRL_3, 0x0); if (ret) { @@ -663,6 +682,10 @@ static int arizona_runtime_suspend(struct device *dev) } break; default: + jd_active = arizona_is_jack_det_active(arizona); + if (jd_active < 0) + return jd_active; + if (arizona->external_dcvdd) { ret = arizona_isolate_dcvdd(arizona); if (ret != 0) @@ -676,7 +699,7 @@ static int arizona_runtime_suspend(struct device *dev) regulator_disable(arizona->dcvdd); /* Allow us to completely power down if no jack detection */ - if (!(val & ARIZONA_JD1_ENA)) { + if (!jd_active) { dev_dbg(arizona->dev, "Fully powering off\n"); arizona->has_fully_powered_off = true; -- cgit v1.2.3 From 161ad30bd2ec4be7269b2f8748fa4e5d5847191e Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 2 Oct 2015 13:29:12 +0100 Subject: mfd: arizona: Downgrade type mismatch messages to dev_warn If the declared codec type doesn't match the detected type we issue a log message but carry on registering the device, so a dev_warn() is appropriate rather than a dev_err() Signed-off-by: Richard Fitzgerald Acked-by: Lee Jones Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index e32d0d30e9cd..c3f88e57fe4a 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1130,8 +1130,8 @@ int arizona_dev_init(struct arizona *arizona) case 0x5102: type_name = "WM5102"; if (arizona->type != WM5102) { - dev_err(arizona->dev, "WM5102 registered as %d\n", - arizona->type); + dev_warn(arizona->dev, "WM5102 registered as %d\n", + arizona->type); arizona->type = WM5102; } apply_patch = wm5102_patch; @@ -1149,8 +1149,8 @@ int arizona_dev_init(struct arizona *arizona) break; default: type_name = "WM5110"; - dev_err(arizona->dev, "WM5110 registered as %d\n", - arizona->type); + dev_warn(arizona->dev, "WM5110 registered as %d\n", + arizona->type); arizona->type = WM5110; break; } @@ -1161,8 +1161,8 @@ int arizona_dev_init(struct arizona *arizona) case 0x8997: type_name = "WM8997"; if (arizona->type != WM8997) { - dev_err(arizona->dev, "WM8997 registered as %d\n", - arizona->type); + dev_warn(arizona->dev, "WM8997 registered as %d\n", + arizona->type); arizona->type = WM8997; } apply_patch = wm8997_patch; @@ -1181,8 +1181,8 @@ int arizona_dev_init(struct arizona *arizona) default: type_name = "WM8998"; - dev_err(arizona->dev, "WM8998 registered as %d\n", - arizona->type); + dev_warn(arizona->dev, "WM8998 registered as %d\n", + arizona->type); arizona->type = WM8998; } -- cgit v1.2.3 From ae05ea36d1c9bdc76a4539277d96f5bdf3d39f02 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 2 Oct 2015 13:29:13 +0100 Subject: mfd: arizona: Simplify adding subdevices The code was using a switch on the code type to execute one of several mfd_add_devices() calls. We're already switching on the code type earlier in the function to select the correct patch function so we can roll selection of the mfd device table into the same switch. Signed-off-by: Richard Fitzgerald Acked-by: Lee Jones Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index c3f88e57fe4a..39899bf18231 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -965,7 +966,8 @@ int arizona_dev_init(struct arizona *arizona) const char *type_name; unsigned int reg, val, mask; int (*apply_patch)(struct arizona *) = NULL; - int ret, i; + const struct mfd_cell *subdevs = NULL; + int n_subdevs, ret, i; dev_set_drvdata(arizona->dev, arizona); mutex_init(&arizona->clk_lock); @@ -1136,6 +1138,8 @@ int arizona_dev_init(struct arizona *arizona) } apply_patch = wm5102_patch; arizona->rev &= 0x7; + subdevs = wm5102_devs; + n_subdevs = ARRAY_SIZE(wm5102_devs); break; #endif #ifdef CONFIG_MFD_WM5110 @@ -1155,6 +1159,8 @@ int arizona_dev_init(struct arizona *arizona) break; } apply_patch = wm5110_patch; + subdevs = wm5110_devs; + n_subdevs = ARRAY_SIZE(wm5110_devs); break; #endif #ifdef CONFIG_MFD_WM8997 @@ -1166,6 +1172,8 @@ int arizona_dev_init(struct arizona *arizona) arizona->type = WM8997; } apply_patch = wm8997_patch; + subdevs = wm8997_devs; + n_subdevs = ARRAY_SIZE(wm8997_devs); break; #endif #ifdef CONFIG_MFD_WM8998 @@ -1187,6 +1195,8 @@ int arizona_dev_init(struct arizona *arizona) } apply_patch = wm8998_patch; + subdevs = wm8998_devs; + n_subdevs = ARRAY_SIZE(wm8998_devs); break; #endif default: @@ -1379,28 +1389,10 @@ int arizona_dev_init(struct arizona *arizona) arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked", arizona_underclocked, arizona); - switch (arizona->type) { - case WM5102: - ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); - break; - case WM5110: - case WM8280: - ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, - ARRAY_SIZE(wm5110_devs), NULL, 0, NULL); - break; - case WM8997: - ret = mfd_add_devices(arizona->dev, -1, wm8997_devs, - ARRAY_SIZE(wm8997_devs), NULL, 0, NULL); - break; - case WM8998: - case WM1814: - ret = mfd_add_devices(arizona->dev, -1, wm8998_devs, - ARRAY_SIZE(wm8998_devs), NULL, 0, NULL); - break; - } + ret = mfd_add_devices(arizona->dev, PLATFORM_DEVID_NONE, + subdevs, n_subdevs, NULL, 0, NULL); - if (ret != 0) { + if (ret) { dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret); goto err_irq; } -- cgit v1.2.3 From b61c1ec058dabdcbddad7436bb4c009a8fa65b02 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 2 Oct 2015 13:29:14 +0100 Subject: mfd: arizona: Remove use of codec build config #ifdefs Remove the use of #ifdefs around each case statement of the chip ID and type validation switches. We must ensure that the contained code still compiles to nothing if support for that codec was not built into the kernel, to prevent creation of link references to missing functions. So the ifdefs are replaced with a use of the IS_ENABLED() macro. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 129 +++++++++++++++++++++++++-------------------- drivers/mfd/arizona-i2c.c | 28 +++++----- drivers/mfd/arizona-spi.c | 18 ++++--- 3 files changed, 97 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 39899bf18231..4e49210f7a5b 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1128,82 +1128,95 @@ int arizona_dev_init(struct arizona *arizona) arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; switch (reg) { -#ifdef CONFIG_MFD_WM5102 case 0x5102: - type_name = "WM5102"; - if (arizona->type != WM5102) { - dev_warn(arizona->dev, "WM5102 registered as %d\n", - arizona->type); - arizona->type = WM5102; + if (IS_ENABLED(CONFIG_MFD_WM5102)) { + type_name = "WM5102"; + if (arizona->type != WM5102) { + dev_warn(arizona->dev, + "WM5102 registered as %d\n", + arizona->type); + arizona->type = WM5102; + } + + apply_patch = wm5102_patch; + arizona->rev &= 0x7; + subdevs = wm5102_devs; + n_subdevs = ARRAY_SIZE(wm5102_devs); } - apply_patch = wm5102_patch; - arizona->rev &= 0x7; - subdevs = wm5102_devs; - n_subdevs = ARRAY_SIZE(wm5102_devs); break; -#endif -#ifdef CONFIG_MFD_WM5110 case 0x5110: - switch (arizona->type) { - case WM5110: - type_name = "WM5110"; - break; - case WM8280: - type_name = "WM8280"; - break; - default: - type_name = "WM5110"; - dev_warn(arizona->dev, "WM5110 registered as %d\n", - arizona->type); - arizona->type = WM5110; - break; + if (IS_ENABLED(CONFIG_MFD_WM5110)) { + switch (arizona->type) { + case WM5110: + type_name = "WM5110"; + break; + case WM8280: + type_name = "WM8280"; + break; + default: + type_name = "WM5110"; + dev_warn(arizona->dev, + "WM5110 registered as %d\n", + arizona->type); + arizona->type = WM5110; + break; + } + + apply_patch = wm5110_patch; + subdevs = wm5110_devs; + n_subdevs = ARRAY_SIZE(wm5110_devs); } - apply_patch = wm5110_patch; - subdevs = wm5110_devs; - n_subdevs = ARRAY_SIZE(wm5110_devs); break; -#endif -#ifdef CONFIG_MFD_WM8997 case 0x8997: - type_name = "WM8997"; - if (arizona->type != WM8997) { - dev_warn(arizona->dev, "WM8997 registered as %d\n", - arizona->type); - arizona->type = WM8997; + if (IS_ENABLED(CONFIG_MFD_WM8997)) { + type_name = "WM8997"; + if (arizona->type != WM8997) { + dev_warn(arizona->dev, + "WM8997 registered as %d\n", + arizona->type); + arizona->type = WM8997; + } + + apply_patch = wm8997_patch; + subdevs = wm8997_devs; + n_subdevs = ARRAY_SIZE(wm8997_devs); } - apply_patch = wm8997_patch; - subdevs = wm8997_devs; - n_subdevs = ARRAY_SIZE(wm8997_devs); break; -#endif -#ifdef CONFIG_MFD_WM8998 case 0x6349: - switch (arizona->type) { - case WM8998: - type_name = "WM8998"; - break; - - case WM1814: - type_name = "WM1814"; - break; + if (IS_ENABLED(CONFIG_MFD_WM8998)) { + switch (arizona->type) { + case WM8998: + type_name = "WM8998"; + break; + + case WM1814: + type_name = "WM1814"; + break; + + default: + type_name = "WM8998"; + dev_warn(arizona->dev, + "WM8998 registered as %d\n", + arizona->type); + arizona->type = WM8998; + } - default: - type_name = "WM8998"; - dev_warn(arizona->dev, "WM8998 registered as %d\n", - arizona->type); - arizona->type = WM8998; + apply_patch = wm8998_patch; + subdevs = wm8998_devs; + n_subdevs = ARRAY_SIZE(wm8998_devs); } - - apply_patch = wm8998_patch; - subdevs = wm8998_devs; - n_subdevs = ARRAY_SIZE(wm8998_devs); break; -#endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); goto err_reset; } + if (!subdevs) { + dev_err(arizona->dev, + "No kernel support for device ID %x\n", reg); + goto err_reset; + } + dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); if (apply_patch) { diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index cea1b409fa27..914bdce58bdf 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -27,7 +27,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct arizona *arizona; - const struct regmap_config *regmap_config; + const struct regmap_config *regmap_config = NULL; unsigned long type; int ret; @@ -37,34 +37,36 @@ static int arizona_i2c_probe(struct i2c_client *i2c, type = id->driver_data; switch (type) { -#ifdef CONFIG_MFD_WM5102 case WM5102: - regmap_config = &wm5102_i2c_regmap; + if (IS_ENABLED(CONFIG_MFD_WM5102)) + regmap_config = &wm5102_i2c_regmap; break; -#endif -#ifdef CONFIG_MFD_WM5110 case WM5110: case WM8280: - regmap_config = &wm5110_i2c_regmap; + if (IS_ENABLED(CONFIG_MFD_WM5110)) + regmap_config = &wm5110_i2c_regmap; break; -#endif -#ifdef CONFIG_MFD_WM8997 case WM8997: - regmap_config = &wm8997_i2c_regmap; + if (IS_ENABLED(CONFIG_MFD_WM8997)) + regmap_config = &wm8997_i2c_regmap; break; -#endif -#ifdef CONFIG_MFD_WM8998 case WM8998: case WM1814: - regmap_config = &wm8998_i2c_regmap; + if (IS_ENABLED(CONFIG_MFD_WM8998)) + regmap_config = &wm8998_i2c_regmap; break; -#endif default: dev_err(&i2c->dev, "Unknown device type %ld\n", id->driver_data); return -EINVAL; } + if (!regmap_config) { + dev_err(&i2c->dev, + "No kernel support for device type %ld\n", type); + return -EINVAL; + } + arizona = devm_kzalloc(&i2c->dev, sizeof(*arizona), GFP_KERNEL); if (arizona == NULL) return -ENOMEM; diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 1e845f6d407b..850a63a3235e 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -27,7 +27,7 @@ static int arizona_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct arizona *arizona; - const struct regmap_config *regmap_config; + const struct regmap_config *regmap_config = NULL; unsigned long type; int ret; @@ -37,23 +37,27 @@ static int arizona_spi_probe(struct spi_device *spi) type = id->driver_data; switch (type) { -#ifdef CONFIG_MFD_WM5102 case WM5102: - regmap_config = &wm5102_spi_regmap; + if (IS_ENABLED(CONFIG_MFD_WM5102)) + regmap_config = &wm5102_spi_regmap; break; -#endif -#ifdef CONFIG_MFD_WM5110 case WM5110: case WM8280: - regmap_config = &wm5110_spi_regmap; + if (IS_ENABLED(CONFIG_MFD_WM5110)) + regmap_config = &wm5110_spi_regmap; break; -#endif default: dev_err(&spi->dev, "Unknown device type %ld\n", id->driver_data); return -EINVAL; } + if (!regmap_config) { + dev_err(&spi->dev, + "No kernel support for device type %ld\n", type); + return -EINVAL; + } + arizona = devm_kzalloc(&spi->dev, sizeof(*arizona), GFP_KERNEL); if (arizona == NULL) return -ENOMEM; -- cgit v1.2.3 From 2e44e28ad2628cd29a4829ffab06fe7e3b79469c Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 2 Oct 2015 13:29:15 +0100 Subject: mfd: arizona: Use correct type ID for device tree config In the case of a device tree config the code uses the device ID from the DT entry to check which codec is required but when storing the ID into struct arizona it was always using the non-DT SPI device table to get an ID. This patch changes the code to store the correct ID into struct arizona. Signed-off-by: Richard Fitzgerald Acked-by: Lee Jones Signed-off-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-i2c.c | 5 ++--- drivers/mfd/arizona-spi.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index 914bdce58bdf..4e3afd1861fc 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -56,8 +56,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c, regmap_config = &wm8998_i2c_regmap; break; default: - dev_err(&i2c->dev, "Unknown device type %ld\n", - id->driver_data); + dev_err(&i2c->dev, "Unknown device type %ld\n", type); return -EINVAL; } @@ -79,7 +78,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c, return ret; } - arizona->type = id->driver_data; + arizona->type = type; arizona->dev = &i2c->dev; arizona->irq = i2c->irq; diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 850a63a3235e..8cffb1cfe73d 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -47,8 +47,7 @@ static int arizona_spi_probe(struct spi_device *spi) regmap_config = &wm5110_spi_regmap; break; default: - dev_err(&spi->dev, "Unknown device type %ld\n", - id->driver_data); + dev_err(&spi->dev, "Unknown device type %ld\n", type); return -EINVAL; } @@ -70,7 +69,7 @@ static int arizona_spi_probe(struct spi_device *spi) return ret; } - arizona->type = id->driver_data; + arizona->type = type; arizona->dev = &spi->dev; arizona->irq = spi->irq; -- cgit v1.2.3 From c2c9f1fe4bf2d6597bbaaab7514d9c9092b5b2f6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 7 Oct 2015 09:44:39 +0900 Subject: mfd: sec-core: Dump PMIC revision to find out the HW There are different revisions of the same chipset. For example S2MPS13 has more than 2 revisions. They differ slightly in regulator constraints. Print the revision number to easily find which PMIC is used on the board. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 2d1137a7a0ee..589e5efc2d7f 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -253,6 +253,15 @@ static const struct regmap_config s5m8767_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic) +{ + unsigned int val; + + /* For each device type, the REG_ID is always the first register */ + if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val)) + dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val); +} + #ifdef CONFIG_OF /* * Only the common platform data elements for s5m8767 are parsed here from the @@ -425,6 +434,7 @@ static int sec_pmic_probe(struct i2c_client *i2c, goto err_mfd; device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); + sec_pmic_dump_rev(sec_pmic); return ret; -- cgit v1.2.3 From 8a97d4287e2659f3460a8dec61ccc935154726c0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 7 Oct 2015 09:44:41 +0900 Subject: mfd: sec-core: Disable buck voltage reset on watchdog falling edge The WRSTBI bit (disabled by default but enabled by bootloader), when set, is responsible for resetting voltages to default values of certain bucks on falling edge of Warm Reset Input pin from AP. However on some boards (with S2MPS13) the pin is pulled down so any suspend will effectively trigger the reset of bucks supplying the power to the little and big cores. In the same time when resuming, these bucks must provide voltage greater or equal to voltage before suspend to match the frequency chosen by cpufreq. If voltage (default value of voltage after reset) is lower than one set by cpufreq before suspend, then system will hang during resuming. Signed-off-by: Krzysztof Kozlowski Reported-by: Bartlomiej Zolnierkiewicz Tested-by: Bartlomiej Zolnierkiewicz Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 26 ++++++++++++++++++++++++++ include/linux/mfd/samsung/core.h | 2 ++ include/linux/mfd/samsung/s2mps13.h | 1 + 3 files changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 589e5efc2d7f..2626fc0b5b8c 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -262,6 +262,29 @@ static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic) dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val); } +static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic) +{ + int err; + + if (sec_pmic->device_type != S2MPS13X) + return; + + if (sec_pmic->pdata->disable_wrstbi) { + /* + * If WRSTBI pin is pulled down this feature must be disabled + * because each Suspend to RAM will trigger buck voltage reset + * to default values. + */ + err = regmap_update_bits(sec_pmic->regmap_pmic, + S2MPS13_REG_WRSTBI, + S2MPS13_REG_WRSTBI_MASK, 0x0); + if (err) + dev_warn(sec_pmic->dev, + "Cannot initialize WRSTBI config: %d\n", + err); + } +} + #ifdef CONFIG_OF /* * Only the common platform data elements for s5m8767 are parsed here from the @@ -289,6 +312,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( pd->manual_poweroff = of_property_read_bool(dev->of_node, "samsung,s2mps11-acokb-ground"); + pd->disable_wrstbi = of_property_read_bool(dev->of_node, + "samsung,s2mps11-wrstbi-ground"); return pd; } #else @@ -434,6 +459,7 @@ static int sec_pmic_probe(struct i2c_client *i2c, goto err_mfd; device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); + sec_pmic_configure(sec_pmic); sec_pmic_dump_rev(sec_pmic); return ret; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index aa78957e092f..a06098639399 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -134,6 +134,8 @@ struct sec_platform_data { int buck4_init; /* Whether or not manually set PWRHOLD to low during shutdown. */ bool manual_poweroff; + /* Disable the WRSTBI (buck voltage warm reset) when probing? */ + bool disable_wrstbi; }; /** diff --git a/include/linux/mfd/samsung/s2mps13.h b/include/linux/mfd/samsung/s2mps13.h index b1fd675fa36f..239e977ba45d 100644 --- a/include/linux/mfd/samsung/s2mps13.h +++ b/include/linux/mfd/samsung/s2mps13.h @@ -184,5 +184,6 @@ enum s2mps13_regulators { * Let's assume that default value will be set. */ #define S2MPS13_BUCK_RAMP_DELAY 12500 +#define S2MPS13_REG_WRSTBI_MASK BIT(5) #endif /* __LINUX_MFD_S2MPS13_H */ -- cgit v1.2.3 From e56e5ad67d15f775537f1259527f1ad5796da012 Mon Sep 17 00:00:00 2001 From: Borun Fu Date: Wed, 14 Oct 2015 16:16:26 +0800 Subject: mfd: axp20x: Add a cell for the power button part of the, axp288 PMICs This patch adds the mfd cell info for axp288 power key device. Signed-off-by: Borun Fu Signed-off-by: Fei Yang Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 3f576b76c322..9842199e2e6c 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -161,6 +161,21 @@ static struct resource axp22x_pek_resources[] = { }, }; +static struct resource axp288_power_button_resources[] = { + { + .name = "PEK_DBR", + .start = AXP288_IRQ_POKN, + .end = AXP288_IRQ_POKN, + .flags = IORESOURCE_IRQ, + }, + { + .name = "PEK_DBF", + .start = AXP288_IRQ_POKP, + .end = AXP288_IRQ_POKP, + .flags = IORESOURCE_IRQ, + }, +}; + static struct resource axp288_fuel_gauge_resources[] = { { .start = AXP288_IRQ_QWBTU, @@ -571,6 +586,11 @@ static struct mfd_cell axp288_cells[] = { .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), .resources = axp288_fuel_gauge_resources, }, + { + .name = "axp20x-pek", + .num_resources = ARRAY_SIZE(axp288_power_button_resources), + .resources = axp288_power_button_resources, + }, { .name = "axp288_pmic_acpi", }, -- cgit v1.2.3 From a05950a4453fcfb136ee1eff0bd0a3cfb46a401e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 19 Oct 2015 13:18:05 +0300 Subject: mfd: arizona: Signedness bug in arizona_runtime_suspend() The "jd_active" variable needs to be signed for the error handling to work. Fixes: 143e5887ae57 ('mfd: arizona: factor out checking of jack detection state') Signed-off-by: Dan Carpenter Acked-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 4e49210f7a5b..d474732cc65c 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -628,7 +628,7 @@ err: static int arizona_runtime_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); - unsigned int jd_active = 0; + int jd_active = 0; int ret; dev_dbg(arizona->dev, "Entering AoD mode\n"); -- cgit v1.2.3 From 6a636ec0ab19c64e83d1008a80606e1030a0c422 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 21 Oct 2015 12:41:47 +0300 Subject: mfd: lpss: Add Broxton ACPI IDs Intel Broxton has the same LPSS block than Intel Sunrisepoint so add Broxton ACPI IDs to the list. Signed-off-by: Mika Westerberg Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss-acpi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index 0d92d73bfa0e..b6fd9041f82f 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c @@ -25,10 +25,26 @@ static const struct intel_lpss_platform_info spt_info = { .clk_rate = 120000000, }; +static const struct intel_lpss_platform_info bxt_info = { + .clk_rate = 100000000, +}; + +static const struct intel_lpss_platform_info bxt_i2c_info = { + .clk_rate = 133000000, +}; + static const struct acpi_device_id intel_lpss_acpi_ids[] = { /* SPT */ { "INT3446", (kernel_ulong_t)&spt_info }, { "INT3447", (kernel_ulong_t)&spt_info }, + /* BXT */ + { "80860AAC", (kernel_ulong_t)&bxt_i2c_info }, + { "80860ABC", (kernel_ulong_t)&bxt_info }, + { "80860AC2", (kernel_ulong_t)&bxt_info }, + /* APL */ + { "80865AAC", (kernel_ulong_t)&bxt_i2c_info }, + { "80865ABC", (kernel_ulong_t)&bxt_info }, + { "80865AC2", (kernel_ulong_t)&bxt_info }, { } }; MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids); -- cgit v1.2.3 From ff0a04a699b9ea9b795208baff2ae727a6a3085a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 21 Oct 2015 12:41:48 +0300 Subject: mfd: lpss: Add Intel Broxton PCI IDs Intel Broxton has the same LPSS block than Intel Sunrisepoint so add Broxton PCI IDs to the list. Signed-off-by: Mika Westerberg Signed-off-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/intel-lpss-pci.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 9236dffeb4d6..5bfdfccbb9a1 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -70,7 +70,52 @@ static const struct intel_lpss_platform_info spt_uart_info = { .clk_con_id = "baudclk", }; +static const struct intel_lpss_platform_info bxt_info = { + .clk_rate = 100000000, +}; + +static const struct intel_lpss_platform_info bxt_uart_info = { + .clk_rate = 100000000, + .clk_con_id = "baudclk", +}; + +static const struct intel_lpss_platform_info bxt_i2c_info = { + .clk_rate = 133000000, +}; + static const struct pci_device_id intel_lpss_pci_ids[] = { + /* BXT */ + { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0ab0), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0ab2), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0ab4), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0ab6), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0ab8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0aba), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x0abc), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x0abe), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x0ac0), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x0ac2), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x0ac4), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x0ac6), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x0aee), (kernel_ulong_t)&bxt_uart_info }, + /* APL */ + { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x5ac2), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info }, /* SPT-LP */ { PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info }, -- cgit v1.2.3 From b487c17d5ff381943b7c9b6af992eec83ee5c5ee Mon Sep 17 00:00:00 2001 From: Ingi Kim Date: Fri, 23 Oct 2015 14:48:03 +0900 Subject: mfd: rt5033: Add RT5033 Flash led sub device This patch adds rt5033-led sub device to support it. Signed-off-by: Ingi Kim Signed-off-by: Lee Jones --- drivers/mfd/rt5033.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index 110de2a583af..2b95485f0057 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -47,6 +47,9 @@ static const struct mfd_cell rt5033_devs[] = { }, { .name = "rt5033-battery", .of_compatible = "richtek,rt5033-battery", + }, { + .name = "rt5033-led", + .of_compatible = "richtek,rt5033-led", }, }; -- cgit v1.2.3 From 644a3746d9724bda20b7f306113262cdb292baae Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 30 Oct 2015 16:51:21 +0900 Subject: mfd: sec-core: Remove unused s2mpu02-rtc and s2mpu02-clk children The commit 54e8827d5f0e ("mfd: sec-core: Add support for S2MPU02 device") added new MFD child devices for S2MPU02: RTC and clock provider (the clock provider with new compatible). However support for these devices was not added to existing drivers (rtc-s5m, clk-s2mps11). New drivers were not submitted neither. This means that the name of children devices is completely unused. The "samsung,s2mpu02-clk" compatible remains undocumented so it is unclear what is provided by that compatible. Clean up this by removing unused child devices and undocumented compatible. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 2626fc0b5b8c..989076d6cb83 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -103,12 +103,9 @@ static const struct mfd_cell s2mpa01_devs[] = { }; static const struct mfd_cell s2mpu02_devs[] = { - { .name = "s2mpu02-pmic", }, - { .name = "s2mpu02-rtc", }, { - .name = "s2mpu02-clk", - .of_compatible = "samsung,s2mpu02-clk", - } + .name = "s2mpu02-pmic", + }, }; #ifdef CONFIG_OF -- cgit v1.2.3