Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Intel CHT Whiskey Cove PMIC I2C Master driver
0004  * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
0005  *
0006  * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
0007  * Copyright (C) 2011 - 2014 Intel Corporation. All rights reserved.
0008  */
0009 
0010 #include <linux/acpi.h>
0011 #include <linux/completion.h>
0012 #include <linux/delay.h>
0013 #include <linux/i2c.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irq.h>
0016 #include <linux/irqdomain.h>
0017 #include <linux/mfd/intel_soc_pmic.h>
0018 #include <linux/module.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/power/bq24190_charger.h>
0021 #include <linux/power/bq25890_charger.h>
0022 #include <linux/slab.h>
0023 
0024 #define CHT_WC_I2C_CTRL         0x5e24
0025 #define CHT_WC_I2C_CTRL_WR      BIT(0)
0026 #define CHT_WC_I2C_CTRL_RD      BIT(1)
0027 #define CHT_WC_I2C_CLIENT_ADDR      0x5e25
0028 #define CHT_WC_I2C_REG_OFFSET       0x5e26
0029 #define CHT_WC_I2C_WRDATA       0x5e27
0030 #define CHT_WC_I2C_RDDATA       0x5e28
0031 
0032 #define CHT_WC_EXTCHGRIRQ       0x6e0a
0033 #define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ    BIT(0)
0034 #define CHT_WC_EXTCHGRIRQ_WRITE_IRQ BIT(1)
0035 #define CHT_WC_EXTCHGRIRQ_READ_IRQ  BIT(2)
0036 #define CHT_WC_EXTCHGRIRQ_NACK_IRQ  BIT(3)
0037 #define CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK  ((u8)GENMASK(3, 1))
0038 #define CHT_WC_EXTCHGRIRQ_MSK       0x6e17
0039 
0040 struct cht_wc_i2c_adap {
0041     struct i2c_adapter adapter;
0042     wait_queue_head_t wait;
0043     struct irq_chip irqchip;
0044     struct mutex adap_lock;
0045     struct mutex irqchip_lock;
0046     struct regmap *regmap;
0047     struct irq_domain *irq_domain;
0048     struct i2c_client *client;
0049     int client_irq;
0050     u8 irq_mask;
0051     u8 old_irq_mask;
0052     int read_data;
0053     bool io_error;
0054     bool done;
0055 };
0056 
0057 static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
0058 {
0059     struct cht_wc_i2c_adap *adap = data;
0060     int ret, reg;
0061 
0062     mutex_lock(&adap->adap_lock);
0063 
0064     /* Read IRQs */
0065     ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
0066     if (ret) {
0067         dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
0068         mutex_unlock(&adap->adap_lock);
0069         return IRQ_NONE;
0070     }
0071 
0072     reg &= ~adap->irq_mask;
0073 
0074     /* Reads must be acked after reading the received data. */
0075     ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &adap->read_data);
0076     if (ret)
0077         adap->io_error = true;
0078 
0079     /*
0080      * Immediately ack IRQs, so that if new IRQs arrives while we're
0081      * handling the previous ones our irq will re-trigger when we're done.
0082      */
0083     ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
0084     if (ret)
0085         dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
0086 
0087     if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) {
0088         adap->io_error |= !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ);
0089         adap->done = true;
0090     }
0091 
0092     mutex_unlock(&adap->adap_lock);
0093 
0094     if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK)
0095         wake_up(&adap->wait);
0096 
0097     /*
0098      * Do NOT use handle_nested_irq here, the client irq handler will
0099      * likely want to do i2c transfers and the i2c controller uses this
0100      * interrupt handler as well, so running the client irq handler from
0101      * this thread will cause things to lock up.
0102      */
0103     if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ)
0104         generic_handle_irq_safe(adap->client_irq);
0105 
0106     return IRQ_HANDLED;
0107 }
0108 
0109 static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
0110 {
0111     /* This i2c adapter only supports SMBUS byte transfers */
0112     return I2C_FUNC_SMBUS_BYTE_DATA;
0113 }
0114 
0115 static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr,
0116                       unsigned short flags, char read_write,
0117                       u8 command, int size,
0118                       union i2c_smbus_data *data)
0119 {
0120     struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
0121     int ret;
0122 
0123     mutex_lock(&adap->adap_lock);
0124     adap->io_error = false;
0125     adap->done = false;
0126     mutex_unlock(&adap->adap_lock);
0127 
0128     ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr);
0129     if (ret)
0130         return ret;
0131 
0132     if (read_write == I2C_SMBUS_WRITE) {
0133         ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte);
0134         if (ret)
0135             return ret;
0136     }
0137 
0138     ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command);
0139     if (ret)
0140         return ret;
0141 
0142     ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL,
0143                (read_write == I2C_SMBUS_WRITE) ?
0144                CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD);
0145     if (ret)
0146         return ret;
0147 
0148     ret = wait_event_timeout(adap->wait, adap->done, msecs_to_jiffies(30));
0149     if (ret == 0) {
0150         /*
0151          * The CHT GPIO controller serializes all IRQs, sometimes
0152          * causing significant delays, check status manually.
0153          */
0154         cht_wc_i2c_adap_thread_handler(0, adap);
0155         if (!adap->done)
0156             return -ETIMEDOUT;
0157     }
0158 
0159     ret = 0;
0160     mutex_lock(&adap->adap_lock);
0161     if (adap->io_error)
0162         ret = -EIO;
0163     else if (read_write == I2C_SMBUS_READ)
0164         data->byte = adap->read_data;
0165     mutex_unlock(&adap->adap_lock);
0166 
0167     return ret;
0168 }
0169 
0170 static const struct i2c_algorithm cht_wc_i2c_adap_algo = {
0171     .functionality = cht_wc_i2c_adap_master_func,
0172     .smbus_xfer = cht_wc_i2c_adap_smbus_xfer,
0173 };
0174 
0175 /*
0176  * We are an i2c-adapter which itself is part of an i2c-client. This means that
0177  * transfers done through us take adapter->bus_lock twice, once for our parent
0178  * i2c-adapter and once to take our own bus_lock. Lockdep does not like this
0179  * nested locking, to make lockdep happy in the case of busses with muxes, the
0180  * i2c-core's i2c_adapter_lock_bus function calls:
0181  * rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));
0182  *
0183  * But i2c_adapter_depth only works when the direct parent of the adapter is
0184  * another adapter, as it is only meant for muxes. In our case there is an
0185  * i2c-client and MFD instantiated platform_device in the parent->child chain
0186  * between the 2 devices.
0187  *
0188  * So we override the default i2c_lock_operations and pass a hardcoded
0189  * depth of 1 to rt_mutex_lock_nested, to make lockdep happy.
0190  *
0191  * Note that if there were to be a mux attached to our adapter, this would
0192  * break things again since the i2c-mux code expects the root-adapter to have
0193  * a locking depth of 0. But we always have only 1 client directly attached
0194  * in the form of the Charger IC paired with the CHT Whiskey Cove PMIC.
0195  */
0196 static void cht_wc_i2c_adap_lock_bus(struct i2c_adapter *adapter,
0197                  unsigned int flags)
0198 {
0199     rt_mutex_lock_nested(&adapter->bus_lock, 1);
0200 }
0201 
0202 static int cht_wc_i2c_adap_trylock_bus(struct i2c_adapter *adapter,
0203                    unsigned int flags)
0204 {
0205     return rt_mutex_trylock(&adapter->bus_lock);
0206 }
0207 
0208 static void cht_wc_i2c_adap_unlock_bus(struct i2c_adapter *adapter,
0209                    unsigned int flags)
0210 {
0211     rt_mutex_unlock(&adapter->bus_lock);
0212 }
0213 
0214 static const struct i2c_lock_operations cht_wc_i2c_adap_lock_ops = {
0215     .lock_bus =    cht_wc_i2c_adap_lock_bus,
0216     .trylock_bus = cht_wc_i2c_adap_trylock_bus,
0217     .unlock_bus =  cht_wc_i2c_adap_unlock_bus,
0218 };
0219 
0220 /**** irqchip for the client connected to the extchgr i2c adapter ****/
0221 static void cht_wc_i2c_irq_lock(struct irq_data *data)
0222 {
0223     struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
0224 
0225     mutex_lock(&adap->irqchip_lock);
0226 }
0227 
0228 static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
0229 {
0230     struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
0231     int ret;
0232 
0233     if (adap->irq_mask != adap->old_irq_mask) {
0234         ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK,
0235                    adap->irq_mask);
0236         if (ret == 0)
0237             adap->old_irq_mask = adap->irq_mask;
0238         else
0239             dev_err(&adap->adapter.dev, "Error writing EXTCHGRIRQ_MSK\n");
0240     }
0241 
0242     mutex_unlock(&adap->irqchip_lock);
0243 }
0244 
0245 static void cht_wc_i2c_irq_enable(struct irq_data *data)
0246 {
0247     struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
0248 
0249     adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
0250 }
0251 
0252 static void cht_wc_i2c_irq_disable(struct irq_data *data)
0253 {
0254     struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
0255 
0256     adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
0257 }
0258 
0259 static const struct irq_chip cht_wc_i2c_irq_chip = {
0260     .irq_bus_lock       = cht_wc_i2c_irq_lock,
0261     .irq_bus_sync_unlock    = cht_wc_i2c_irq_sync_unlock,
0262     .irq_disable        = cht_wc_i2c_irq_disable,
0263     .irq_enable     = cht_wc_i2c_irq_enable,
0264     .name           = "cht_wc_ext_chrg_irq_chip",
0265 };
0266 
0267 /********** GPD Win / Pocket charger IC settings **********/
0268 static const char * const bq24190_suppliers[] = {
0269     "tcpm-source-psy-i2c-fusb302" };
0270 
0271 static const struct property_entry bq24190_props[] = {
0272     PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_suppliers),
0273     PROPERTY_ENTRY_BOOL("omit-battery-class"),
0274     PROPERTY_ENTRY_BOOL("disable-reset"),
0275     { }
0276 };
0277 
0278 static const struct software_node bq24190_node = {
0279     .properties = bq24190_props,
0280 };
0281 
0282 static struct regulator_consumer_supply fusb302_consumer = {
0283     .supply = "vbus",
0284     /* Must match fusb302 dev_name in intel_cht_int33fe.c */
0285     .dev_name = "i2c-fusb302",
0286 };
0287 
0288 static const struct regulator_init_data bq24190_vbus_init_data = {
0289     .constraints = {
0290         /* The name is used in intel_cht_int33fe.c do not change. */
0291         .name = "cht_wc_usb_typec_vbus",
0292         .valid_ops_mask = REGULATOR_CHANGE_STATUS,
0293     },
0294     .consumer_supplies = &fusb302_consumer,
0295     .num_consumer_supplies = 1,
0296 };
0297 
0298 static struct bq24190_platform_data bq24190_pdata = {
0299     .regulator_init_data = &bq24190_vbus_init_data,
0300 };
0301 
0302 static struct i2c_board_info gpd_win_board_info = {
0303     .type = "bq24190",
0304     .addr = 0x6b,
0305     .dev_name = "bq24190",
0306     .swnode = &bq24190_node,
0307     .platform_data = &bq24190_pdata,
0308 };
0309 
0310 /********** Xiaomi Mi Pad 2 charger IC settings  **********/
0311 static struct regulator_consumer_supply bq2589x_vbus_consumer = {
0312     .supply = "vbus",
0313     .dev_name = "cht_wcove_pwrsrc",
0314 };
0315 
0316 static const struct regulator_init_data bq2589x_vbus_init_data = {
0317     .constraints = {
0318         .valid_ops_mask = REGULATOR_CHANGE_STATUS,
0319     },
0320     .consumer_supplies = &bq2589x_vbus_consumer,
0321     .num_consumer_supplies = 1,
0322 };
0323 
0324 static struct bq25890_platform_data bq2589x_pdata = {
0325     .regulator_init_data = &bq2589x_vbus_init_data,
0326 };
0327 
0328 static const struct property_entry xiaomi_mipad2_props[] = {
0329     PROPERTY_ENTRY_BOOL("linux,skip-reset"),
0330     PROPERTY_ENTRY_BOOL("linux,read-back-settings"),
0331     { }
0332 };
0333 
0334 static const struct software_node xiaomi_mipad2_node = {
0335     .properties = xiaomi_mipad2_props,
0336 };
0337 
0338 static struct i2c_board_info xiaomi_mipad2_board_info = {
0339     .type = "bq25890",
0340     .addr = 0x6a,
0341     .dev_name = "bq25890",
0342     .swnode = &xiaomi_mipad2_node,
0343     .platform_data = &bq2589x_pdata,
0344 };
0345 
0346 /********** Lenovo Yogabook YB1-X90F/-X91F/-X91L charger settings **********/
0347 static const char * const lenovo_yb1_bq25892_suppliers[] = { "cht_wcove_pwrsrc" };
0348 
0349 static const struct property_entry lenovo_yb1_bq25892_props[] = {
0350     PROPERTY_ENTRY_STRING_ARRAY("supplied-from",
0351                     lenovo_yb1_bq25892_suppliers),
0352     PROPERTY_ENTRY_U32("linux,pump-express-vbus-max", 12000000),
0353     PROPERTY_ENTRY_BOOL("linux,skip-reset"),
0354     /*
0355      * The firmware sets everything to the defaults, which leads to a
0356      * somewhat low charge-current of 2048mA and worse to a battery-voltage
0357      * of 4.2V instead of 4.35V (when booted without a charger connected).
0358      * Use our own values instead of "linux,read-back-settings" to fix this.
0359      */
0360     PROPERTY_ENTRY_U32("ti,charge-current", 4224000),
0361     PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
0362     PROPERTY_ENTRY_U32("ti,termination-current", 256000),
0363     PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
0364     PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3500000),
0365     PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
0366     PROPERTY_ENTRY_U32("ti,boost-max-current", 1400000),
0367     PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
0368     { }
0369 };
0370 
0371 static const struct software_node lenovo_yb1_bq25892_node = {
0372     .properties = lenovo_yb1_bq25892_props,
0373 };
0374 
0375 static struct i2c_board_info lenovo_yogabook1_board_info = {
0376     .type = "bq25892",
0377     .addr = 0x6b,
0378     .dev_name = "bq25892",
0379     .swnode = &lenovo_yb1_bq25892_node,
0380     .platform_data = &bq2589x_pdata,
0381 };
0382 
0383 static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
0384 {
0385     struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
0386     struct i2c_board_info *board_info = NULL;
0387     struct cht_wc_i2c_adap *adap;
0388     int ret, reg, irq;
0389 
0390     irq = platform_get_irq(pdev, 0);
0391     if (irq < 0)
0392         return irq;
0393 
0394     adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
0395     if (!adap)
0396         return -ENOMEM;
0397 
0398     init_waitqueue_head(&adap->wait);
0399     mutex_init(&adap->adap_lock);
0400     mutex_init(&adap->irqchip_lock);
0401     adap->irqchip = cht_wc_i2c_irq_chip;
0402     adap->regmap = pmic->regmap;
0403     adap->adapter.owner = THIS_MODULE;
0404     adap->adapter.class = I2C_CLASS_HWMON;
0405     adap->adapter.algo = &cht_wc_i2c_adap_algo;
0406     adap->adapter.lock_ops = &cht_wc_i2c_adap_lock_ops;
0407     strscpy(adap->adapter.name, "PMIC I2C Adapter",
0408         sizeof(adap->adapter.name));
0409     adap->adapter.dev.parent = &pdev->dev;
0410 
0411     /* Clear and activate i2c-adapter interrupts, disable client IRQ */
0412     adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK;
0413 
0414     ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &reg);
0415     if (ret)
0416         return ret;
0417 
0418     ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask);
0419     if (ret)
0420         return ret;
0421 
0422     ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask);
0423     if (ret)
0424         return ret;
0425 
0426     /* Alloc and register client IRQ */
0427     adap->irq_domain = irq_domain_add_linear(NULL, 1, &irq_domain_simple_ops, NULL);
0428     if (!adap->irq_domain)
0429         return -ENOMEM;
0430 
0431     adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
0432     if (!adap->client_irq) {
0433         ret = -ENOMEM;
0434         goto remove_irq_domain;
0435     }
0436 
0437     irq_set_chip_data(adap->client_irq, adap);
0438     irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
0439                  handle_simple_irq);
0440 
0441     ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0442                     cht_wc_i2c_adap_thread_handler,
0443                     IRQF_ONESHOT, "PMIC I2C Adapter", adap);
0444     if (ret)
0445         goto remove_irq_domain;
0446 
0447     i2c_set_adapdata(&adap->adapter, adap);
0448     ret = i2c_add_adapter(&adap->adapter);
0449     if (ret)
0450         goto remove_irq_domain;
0451 
0452     switch (pmic->cht_wc_model) {
0453     case INTEL_CHT_WC_GPD_WIN_POCKET:
0454         board_info = &gpd_win_board_info;
0455         break;
0456     case INTEL_CHT_WC_XIAOMI_MIPAD2:
0457         board_info = &xiaomi_mipad2_board_info;
0458         break;
0459     case INTEL_CHT_WC_LENOVO_YOGABOOK1:
0460         board_info = &lenovo_yogabook1_board_info;
0461         break;
0462     default:
0463         dev_warn(&pdev->dev, "Unknown model, not instantiating charger device\n");
0464         break;
0465     }
0466 
0467     if (board_info) {
0468         board_info->irq = adap->client_irq;
0469         adap->client = i2c_new_client_device(&adap->adapter, board_info);
0470         if (IS_ERR(adap->client)) {
0471             ret = PTR_ERR(adap->client);
0472             goto del_adapter;
0473         }
0474     }
0475 
0476     platform_set_drvdata(pdev, adap);
0477     return 0;
0478 
0479 del_adapter:
0480     i2c_del_adapter(&adap->adapter);
0481 remove_irq_domain:
0482     irq_domain_remove(adap->irq_domain);
0483     return ret;
0484 }
0485 
0486 static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
0487 {
0488     struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
0489 
0490     i2c_unregister_device(adap->client);
0491     i2c_del_adapter(&adap->adapter);
0492     irq_domain_remove(adap->irq_domain);
0493 
0494     return 0;
0495 }
0496 
0497 static const struct platform_device_id cht_wc_i2c_adap_id_table[] = {
0498     { .name = "cht_wcove_ext_chgr" },
0499     {},
0500 };
0501 MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
0502 
0503 static struct platform_driver cht_wc_i2c_adap_driver = {
0504     .probe = cht_wc_i2c_adap_i2c_probe,
0505     .remove = cht_wc_i2c_adap_i2c_remove,
0506     .driver = {
0507         .name = "cht_wcove_ext_chgr",
0508     },
0509     .id_table = cht_wc_i2c_adap_id_table,
0510 };
0511 module_platform_driver(cht_wc_i2c_adap_driver);
0512 
0513 MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver");
0514 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0515 MODULE_LICENSE("GPL");