Guest User

drivers/mfd/intel_soc_pmic_dc.c

a guest
Jun 21st, 2016
355
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Dollar Cove  --  Device access for Intel PMIC for CR
  3.  *
  4.  * Copyright (c) 2014, Intel Corporation.
  5.  *
  6.  * Author: Yang Bin <bin.yang@intel.com>
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License
  10.  * as published by the Free Software Foundation; version 2
  11.  * of the License.
  12.  */
  13.  
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/delay.h>
  17. #include <linux/mfd/core.h>
  18. #include <linux/err.h>
  19. #include <linux/i2c.h>
  20. #include <linux/irq.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/gpio.h>
  23. #include <linux/mfd/intel_soc_pmic.h>
  24. #include <linux/acpi.h>
  25. #include <linux/version.h>
  26. #include <linux/power/dc_xpwr_battery.h>
  27. #include <linux/power/dc_xpwr_charger.h>
  28. #include <linux/regulator/intel_dollar_cove_pmic.h>
  29.  
  30. #include <asm/intel_em_config.h>
  31. #include <linux/extcon/extcon-dc-pwrsrc.h>
  32. #include <linux/power/battery_id.h>
  33.  
  34. #include "intel_soc_pmic_core.h"
  35.  
  36. #define XPOWER_DEFAULT_TEMP_MAX 45
  37.  
  38. #define GPIO_USB_MUX_INDEX      1
  39. #define GPIO_OTG_VBUS_INDEX     2
  40.  
  41. enum {
  42.         VBUS_FALLING_IRQ = 2,
  43.         VBUS_RISING_IRQ,
  44.         VBUS_OV_IRQ,
  45.         VBUS_FALLING_ALT_IRQ,
  46.         VBUS_RISING_ALT_IRQ,
  47.         VBUS_OV_ALT_IRQ,
  48.  
  49.         CHARGE_DONE_IRQ = 10,
  50.         CHARGE_CHARGING_IRQ,
  51.         BAT_SAFE_QUIT_IRQ,
  52.         BAT_SAFE_ENTER_IRQ,
  53.         BAT_ABSENT_IRQ,
  54.         BAT_APPEND_IRQ,
  55.  
  56.         QWBTU_IRQ = 16,
  57.         WBTU_IRQ,
  58.         QWBTO_IRQ,
  59.         WBTO_IRQ,
  60.         QCBTU_IRQ,
  61.         CBTU_IRQ,
  62.         QCBTO_IRQ,
  63.         CBTO_IRQ,
  64.  
  65.         WL2_IRQ = 24,
  66.         WL1_IRQ,
  67.         GPADC_IRQ,
  68.         OT_IRQ = 31,
  69.  
  70.         GPIO0_IRQ = 32,
  71.         GPIO1_IRQ,
  72.         POKO_IRQ,
  73.         POKL_IRQ,
  74.         POKS_IRQ,
  75.         POKN_IRQ,
  76.         POKP_IRQ,
  77.         EVENT_IRQ,
  78.  
  79.         MV_CHNG_IRQ = 40,
  80.         BC_USB_CHNG_IRQ,
  81. };
  82.  
  83. static struct resource power_button_resources[] = {
  84.         {
  85.                 .start  = POKN_IRQ,
  86.                 .end    = POKN_IRQ,
  87.                 .flags  = IORESOURCE_IRQ,
  88.         },
  89.         {
  90.                 .start  = POKP_IRQ,
  91.                 .end    = POKP_IRQ,
  92.                 .flags  = IORESOURCE_IRQ,
  93.         },
  94. };
  95.  
  96.  
  97. static struct resource gpio_resources[] = {
  98.         {
  99.                 .start  = GPIO0_IRQ,
  100.                 .end    = GPIO1_IRQ,
  101.                 .flags  = IORESOURCE_IRQ,
  102.         },
  103. };
  104.  
  105. static struct resource adc_resources[] = {
  106.         {
  107.                 .start = GPADC_IRQ,
  108.                 .end   = GPADC_IRQ,
  109.                 .flags = IORESOURCE_IRQ,
  110.         },
  111. };
  112.  
  113. static struct resource pwrsrc_resources[] = {
  114.         {
  115.                 .start = VBUS_FALLING_IRQ,
  116.                 .end   = VBUS_FALLING_IRQ,
  117.                 .flags = IORESOURCE_IRQ,
  118.         },
  119.         {
  120.                 .start = VBUS_RISING_IRQ,
  121.                 .end   = VBUS_RISING_IRQ,
  122.                 .flags = IORESOURCE_IRQ,
  123.         },
  124.         {
  125.                 .start = MV_CHNG_IRQ,
  126.                 .end   = MV_CHNG_IRQ,
  127.                 .flags = IORESOURCE_IRQ,
  128.         },
  129.         {
  130.                 .start = BC_USB_CHNG_IRQ,
  131.                 .end   = BC_USB_CHNG_IRQ,
  132.                 .flags = IORESOURCE_IRQ,
  133.         },
  134. };
  135.  
  136. static struct resource charger_resources[] = {
  137.         {
  138.                 .start = VBUS_OV_IRQ,
  139.                 .end   = VBUS_OV_IRQ,
  140.                 .flags = IORESOURCE_IRQ,
  141.         },
  142.         {
  143.                 .start = CHARGE_DONE_IRQ,
  144.                 .end   = CHARGE_DONE_IRQ,
  145.                 .flags = IORESOURCE_IRQ,
  146.         },
  147.         {
  148.                 .start = CHARGE_CHARGING_IRQ,
  149.                 .end   = CHARGE_CHARGING_IRQ,
  150.                 .flags = IORESOURCE_IRQ,
  151.         },
  152.         {
  153.                 .start = BAT_SAFE_QUIT_IRQ,
  154.                 .end   = BAT_SAFE_QUIT_IRQ,
  155.                 .flags = IORESOURCE_IRQ,
  156.         },
  157.         {
  158.                 .start = BAT_SAFE_ENTER_IRQ,
  159.                 .end   = BAT_SAFE_ENTER_IRQ,
  160.                 .flags = IORESOURCE_IRQ,
  161.         },
  162.         {
  163.                 .start = QCBTU_IRQ,
  164.                 .end   = QCBTU_IRQ,
  165.                 .flags = IORESOURCE_IRQ,
  166.         },
  167.         {
  168.                 .start = CBTU_IRQ,
  169.                 .end   = CBTU_IRQ,
  170.                 .flags = IORESOURCE_IRQ,
  171.         },
  172.         {
  173.                 .start = QCBTO_IRQ,
  174.                 .end   = QCBTO_IRQ,
  175.                 .flags = IORESOURCE_IRQ,
  176.         },
  177.         {
  178.                 .start = CBTO_IRQ,
  179.                 .end   = CBTO_IRQ,
  180.                 .flags = IORESOURCE_IRQ,
  181.         },
  182. };
  183.  
  184. static struct resource battery_resources[] = {
  185.         {
  186.                 .start = QWBTU_IRQ,
  187.                 .end   = QWBTU_IRQ,
  188.                 .flags = IORESOURCE_IRQ,
  189.         },
  190.         {
  191.                 .start = WBTU_IRQ,
  192.                 .end   = WBTU_IRQ,
  193.                 .flags = IORESOURCE_IRQ,
  194.         },
  195.         {
  196.                 .start = QWBTO_IRQ,
  197.                 .end   = QWBTO_IRQ,
  198.                 .flags = IORESOURCE_IRQ,
  199.         },
  200.         {
  201.                 .start = WBTO_IRQ,
  202.                 .end   = WBTO_IRQ,
  203.                 .flags = IORESOURCE_IRQ,
  204.         },
  205.         {
  206.                 .start = WL2_IRQ,
  207.                 .end   = WL2_IRQ,
  208.                 .flags = IORESOURCE_IRQ,
  209.         },
  210.         {
  211.                 .start = WL1_IRQ,
  212.                 .end   = WL1_IRQ,
  213.                 .flags = IORESOURCE_IRQ,
  214.         },
  215. };
  216.  
  217. static struct mfd_cell dollar_cove_dev[] = {
  218.         {
  219.                 .name = "dollar_cove_adc",
  220.                 .id = 0,
  221.                 .num_resources = ARRAY_SIZE(adc_resources),
  222.                 .resources = adc_resources,
  223.         },
  224.         {
  225.                 .name = "dollar_cove_gpio",
  226.                 .id = 0,
  227.                 .num_resources = ARRAY_SIZE(gpio_resources),
  228.                 .resources = gpio_resources,
  229.         },
  230.         {
  231.                 .name = "dollar_cove_power_button",
  232.                 .id = 0,
  233.                 .num_resources = ARRAY_SIZE(power_button_resources),
  234.                 .resources = power_button_resources,
  235.         },
  236.         {
  237.                 .name = "dollar_cove_pwrsrc",
  238.                 .id = 0,
  239.                 .num_resources = ARRAY_SIZE(pwrsrc_resources),
  240.                 .resources = pwrsrc_resources,
  241.         },
  242.         {
  243.                 .name = "dollar_cove_charger",
  244.                 .id = 0,
  245.                 .num_resources = ARRAY_SIZE(charger_resources),
  246.                 .resources = charger_resources,
  247.         },
  248.         {
  249.                 .name = "dollar_cove_battery",
  250.                 .id = 0,
  251.                 .num_resources = ARRAY_SIZE(battery_resources),
  252.                 .resources = battery_resources,
  253.         },
  254.         {
  255.                 .name = "dollar_cove_region",
  256.         },
  257.         {
  258.                 .name = "dcovex_regulator",
  259.                 .id = DCOVEX_ID_LDO2 + 1,
  260.                 .num_resources = 0,
  261.                 .resources = NULL,
  262.         },
  263.         {
  264.                 .name = "dcovex_regulator",
  265.                 .id = DCOVEX_ID_LDO3 + 1,
  266.                 .num_resources = 0,
  267.                 .resources = NULL,
  268.         },
  269.         {NULL, },
  270. };
  271.  
  272. #define DOLLAR_COVE_IRQREGMAP(irq) \
  273.         [irq] = { \
  274.                 {(0x40 + (irq / 8)), (irq % 8), 1, INTEL_PMIC_REG_INV},\
  275.                 {(0x48 + (irq / 8)), (irq % 8), 1, INTEL_PMIC_REG_W1C},\
  276.                 {(0x48 + (irq / 8)), (irq % 8), 1, INTEL_PMIC_REG_W1C},\
  277.         }
  278.  
  279. struct intel_pmic_irqregmap dollar_cove_irqregmap[] = {
  280.         DOLLAR_COVE_IRQREGMAP(VBUS_FALLING_IRQ),
  281.         DOLLAR_COVE_IRQREGMAP(VBUS_RISING_IRQ),
  282.         DOLLAR_COVE_IRQREGMAP(VBUS_OV_IRQ),
  283.         DOLLAR_COVE_IRQREGMAP(VBUS_FALLING_ALT_IRQ),
  284.         DOLLAR_COVE_IRQREGMAP(VBUS_RISING_ALT_IRQ),
  285.         DOLLAR_COVE_IRQREGMAP(VBUS_OV_ALT_IRQ),
  286.         DOLLAR_COVE_IRQREGMAP(CHARGE_DONE_IRQ),
  287.         DOLLAR_COVE_IRQREGMAP(CHARGE_CHARGING_IRQ),
  288.         DOLLAR_COVE_IRQREGMAP(BAT_SAFE_QUIT_IRQ),
  289.         DOLLAR_COVE_IRQREGMAP(BAT_SAFE_ENTER_IRQ),
  290.         DOLLAR_COVE_IRQREGMAP(BAT_ABSENT_IRQ),
  291.         DOLLAR_COVE_IRQREGMAP(BAT_APPEND_IRQ),
  292.         DOLLAR_COVE_IRQREGMAP(QWBTU_IRQ),
  293.         DOLLAR_COVE_IRQREGMAP(WBTU_IRQ),
  294.         DOLLAR_COVE_IRQREGMAP(QWBTO_IRQ),
  295.         DOLLAR_COVE_IRQREGMAP(WBTO_IRQ),
  296.         DOLLAR_COVE_IRQREGMAP(QCBTU_IRQ),
  297.         DOLLAR_COVE_IRQREGMAP(CBTU_IRQ),
  298.         DOLLAR_COVE_IRQREGMAP(QCBTO_IRQ),
  299.         DOLLAR_COVE_IRQREGMAP(CBTO_IRQ),
  300.         DOLLAR_COVE_IRQREGMAP(WL2_IRQ),
  301.         DOLLAR_COVE_IRQREGMAP(WL1_IRQ),
  302.         DOLLAR_COVE_IRQREGMAP(GPADC_IRQ),
  303.         DOLLAR_COVE_IRQREGMAP(OT_IRQ),
  304.         DOLLAR_COVE_IRQREGMAP(GPIO0_IRQ),
  305.         DOLLAR_COVE_IRQREGMAP(GPIO1_IRQ),
  306.         DOLLAR_COVE_IRQREGMAP(POKO_IRQ),
  307.         DOLLAR_COVE_IRQREGMAP(POKL_IRQ),
  308.         DOLLAR_COVE_IRQREGMAP(POKS_IRQ),
  309.         DOLLAR_COVE_IRQREGMAP(POKN_IRQ),
  310.         DOLLAR_COVE_IRQREGMAP(POKP_IRQ),
  311.         DOLLAR_COVE_IRQREGMAP(EVENT_IRQ),
  312.         DOLLAR_COVE_IRQREGMAP(MV_CHNG_IRQ),
  313.         DOLLAR_COVE_IRQREGMAP(BC_USB_CHNG_IRQ),
  314. };
  315.  
  316.  
  317. static struct ps_batt_chg_prof ps_batt_chrg_prof;
  318. static struct ps_pse_mod_prof *pse_mod_prof;
  319. #ifdef CONFIG_POWER_SUPPLY_CHARGER
  320.  
  321. #define DC_CHRG_CHRG_CUR_NOLIMIT        1800
  322. #define DC_CHRG_CHRG_CUR_MEDIUM         1400
  323. #define DC_CHRG_CHRG_CUR_LOW            1000
  324.  
  325. static struct power_supply_throttle dc_chrg_throttle_states[] = {
  326.         {
  327.                 .throttle_action = PSY_THROTTLE_CC_LIMIT,
  328.                 .throttle_val = DC_CHRG_CHRG_CUR_NOLIMIT,
  329.         },
  330.         {
  331.                 .throttle_action = PSY_THROTTLE_CC_LIMIT,
  332.                 .throttle_val = DC_CHRG_CHRG_CUR_MEDIUM,
  333.         },
  334.         {
  335.                 .throttle_action = PSY_THROTTLE_CC_LIMIT,
  336.                 .throttle_val = DC_CHRG_CHRG_CUR_LOW,
  337.         },
  338.         {
  339.                 .throttle_action = PSY_THROTTLE_DISABLE_CHARGING,
  340.         },
  341. };
  342.  
  343. static char *dc_chrg_supplied_to[] = {
  344.         "dollar_cove_battery"
  345. };
  346.  
  347. static void *platform_get_batt_charge_profile(void)
  348. {
  349.         int ret;
  350.  
  351.         ret = get_batt_prop(&ps_batt_chrg_prof);
  352.         pse_mod_prof = (struct ps_pse_mod_prof *)
  353.                                         ps_batt_chrg_prof.batt_prof;
  354.         if ((ret < 0 || ps_batt_chrg_prof.chrg_prof_type == CHRG_PROF_NONE)
  355.                 && pse_mod_prof)
  356.                         snprintf(pse_mod_prof->batt_id, (BATTID_STR_LEN + 1),
  357.                                 "%s", BATTID_UNKNOWN);
  358.  
  359.         return &ps_batt_chrg_prof;
  360. }
  361.  
  362. static void platform_init_chrg_params(struct dollarcove_chrg_pdata *pdata)
  363. {
  364.         pdata->throttle_states = dc_chrg_throttle_states;
  365.         pdata->supplied_to = dc_chrg_supplied_to;
  366.         pdata->num_throttle_states = ARRAY_SIZE(dc_chrg_throttle_states);
  367.         pdata->num_supplicants = ARRAY_SIZE(dc_chrg_supplied_to);
  368.         pdata->supported_cables = POWER_SUPPLY_CHARGER_TYPE_USB;
  369.         pdata->chg_profile = (struct ps_batt_chg_prof *)
  370.                         platform_get_batt_charge_profile();
  371. }
  372.  
  373. static void platform_set_battery_data(struct dollarcove_fg_pdata *pdata,
  374.         struct ps_batt_chg_prof *chg_prof)
  375. {
  376.         struct ps_pse_mod_prof *prof = (struct ps_pse_mod_prof *)
  377.                 chg_prof->batt_prof;
  378.  
  379.         /*
  380.          * Get the data from ACPI Table OEM0 if it is available
  381.          * Also make sure we are not setting value of 0 as acpi table may
  382.          * sometimes incorrectly set them to 0.
  383.          */
  384.         if (chg_prof->chrg_prof_type == PSE_MOD_CHRG_PROF) {
  385.                 pdata->design_cap = prof->capacity ? prof->capacity : 4045;
  386.                 pdata->design_max_volt = prof->voltage_max ? prof->voltage_max : 4350;
  387.                 pdata->design_min_volt = prof->low_batt_mV ? prof->low_batt_mV : 3400;
  388.         } else {
  389.                 pdata->design_cap = 4045;
  390.                 pdata->design_max_volt = 4350;
  391.                 pdata->design_min_volt = 3400;
  392.         }
  393. }
  394.  
  395. #else
  396.  
  397. static void platform_init_chrg_params(struct dollarcove_chrg_pdata *pdata)
  398. {
  399. }
  400.  
  401. static void platform_set_battery_data(struct dollarcove_fg_pdata *pdata,
  402.         struct ps_batt_chg_prof *chg_prof)
  403. {
  404.         pdata->design_cap = 4045;
  405.         pdata->design_max_volt = 4350;
  406.         pdata->design_min_volt = 3400;
  407. }
  408.  
  409. #endif
  410.  
  411. static void dc_xpwr_chrg_pdata(void)
  412. {
  413.         static struct dollarcove_chrg_pdata pdata;
  414.         struct gpio_desc *gpio_desc;
  415.         struct ps_pse_mod_prof *prof;
  416.         int i, diff;
  417.         struct ps_temp_chg_table *entry;
  418.  
  419.         /* Default parameters */
  420.         pdata.max_cc = 2000;
  421.         pdata.max_cv = 4350;
  422.         pdata.def_cc = 500;
  423.         pdata.def_cv = 4350;
  424.         pdata.def_ilim = 900;
  425.         pdata.def_iterm = 300;
  426.         pdata.def_max_temp = 55;
  427.         pdata.def_min_temp = 0;
  428.  
  429.         gpio_desc = devm_gpiod_get_index(dollar_cove_pmic.dev,
  430.                         "pmic_res", GPIO_OTG_VBUS_INDEX);
  431.         if (IS_ERR(gpio_desc))
  432.                 pdata.otg_gpio = -1;
  433.         else {
  434.                 pdata.otg_gpio = desc_to_gpio(gpio_desc);
  435.                 gpiod_put(gpio_desc);
  436.         }
  437.  
  438.         platform_init_chrg_params(&pdata);
  439.  
  440.         /* Do some sanity checks */
  441.         prof = (struct ps_pse_mod_prof *)pdata.chg_profile->batt_prof;
  442.         pdata.max_cv = min_t(u16, pdata.max_cv, prof->voltage_max);
  443.         pdata.def_cv = min_t(u16, pdata.def_cv, prof->voltage_max);
  444.  
  445.         for (i = 0; i < prof->temp_mon_ranges; i++) {
  446.                 entry = &prof->temp_mon_range[i];
  447.  
  448.                 if (entry->full_chrg_vol > pdata.max_cv)
  449.                         entry->full_chrg_vol = pdata.max_cv;
  450.  
  451.                 if (entry->maint_chrg_vol_ul > pdata.max_cv) {
  452.                         diff = entry->maint_chrg_vol_ul
  453.                                 - entry->maint_chrg_vol_ll;
  454.  
  455.                         entry->maint_chrg_vol_ul = pdata.max_cv;
  456.                         entry->maint_chrg_vol_ll = pdata.max_cv - diff;
  457.                 }
  458.         }
  459.  
  460.         intel_soc_pmic_set_pdata("dollar_cove_charger",
  461.                                 (void *)&pdata, sizeof(pdata), 0);
  462. }
  463.  
  464. static u8 fg_bat_curve_4350mv[] = {
  465.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
  466.         0x02, 0x03, 0x05, 0x09, 0x0f, 0x18, 0x24, 0x29,
  467.         0x2e, 0x32, 0x35, 0x3b, 0x40, 0x45, 0x49, 0x4c,
  468.         0x50, 0x53, 0x55, 0x57, 0x5a, 0x5d, 0x61, 0x64,
  469. };
  470.  
  471. static u8 fg_bat_curve_4200mv[] = {
  472.         0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
  473.         0x02, 0x02, 0x04, 0x0b, 0x12, 0x1b, 0x27, 0x2e,
  474.         0x32, 0x36, 0x3a, 0x40, 0x45, 0x4a, 0x4e, 0x52,
  475.         0x57, 0x5b, 0x5e, 0x61, 0x64, 0x64, 0x64, 0x64,
  476. };
  477.  
  478. #ifdef CONFIG_ACPI
  479. #define FGCONFIG_ACPI_TABLE_NAME        "BCFG"
  480. #define XPWR_FGCONFIG_NAME              "XPOWER-0"
  481.  
  482. static int
  483. dc_xpwr_get_acpi_cdata(struct dollarcove_fg_pdata *pdata)
  484. {
  485.         struct dc_xpwr_acpi_fg_config *acpi_tbl = NULL;
  486.         char *name = FGCONFIG_ACPI_TABLE_NAME;
  487.         acpi_size tbl_size;
  488.         acpi_status status;
  489.  
  490.         /* read the fg config table from acpi */
  491.         status = acpi_get_table_with_size(name , 0,
  492.                         (struct acpi_table_header **)&acpi_tbl, &tbl_size);
  493.         if (ACPI_FAILURE(status)) {
  494.                 pr_err("%s:%s table not found!!\n", __func__, name);
  495.                 return status;
  496.         }
  497.         pr_info("%s: %s table found, size=%d\n",
  498.                                 __func__, name, (int)tbl_size);
  499.  
  500.         /* validate the table size */
  501.         if (tbl_size <  sizeof(struct dc_xpwr_acpi_fg_config)) {
  502.                 pr_err("%s:%s table incomplete!!\n", __func__, name);
  503.                 pr_info("%s: table_size=%d, structure_size=%lu\n",
  504.                         __func__, (int)tbl_size,
  505.                         sizeof(struct dc_xpwr_acpi_fg_config));
  506.                 return -ENXIO;
  507.         }
  508.  
  509.         if (strncmp(acpi_tbl->cdata.fg_name, XPWR_FGCONFIG_NAME,
  510.                 ACPI_FG_CONF_NAME_LEN)
  511.                 || strncmp(acpi_tbl->cdata.battid, pdata->battid,
  512.                 BATTID_STR_LEN)) {
  513.                 pr_err("%s: battid and fg_name mismatch!!!\n", __func__);
  514.                 return -EINVAL;
  515.         }
  516.  
  517.         memcpy(&pdata->cdata, &acpi_tbl->cdata,
  518.                         sizeof(struct dc_xpwr_fg_config_data));
  519.  
  520.         return 0;
  521. }
  522. #endif /* CONFIG_ACPI */
  523.  
  524. static void dc_xpwr_get_fg_config_data(struct dollarcove_fg_pdata *pdata)
  525. {
  526.         int scaled_capacity;
  527.         int i;
  528.         u8 *fg_bat_curve;
  529.  
  530. #ifdef CONFIG_ACPI
  531.         if (!dc_xpwr_get_acpi_cdata(pdata)) {
  532.                 pr_info("%s: Loading fg config from acpi table\n", __func__);
  533.                 pdata->fg_save_restore_enabled = 1;
  534.                 return;
  535.         }
  536. #endif /* CONFIG_ACPI */
  537.  
  538.         pr_info("%s: Loading default fg config.\n", __func__);
  539.         /*
  540.          * Calculate cap1 and cap0.  The value of a LSB is 1.456mAh.
  541.          * Using 1.5 as math friendly and close enough.
  542.          */
  543.  
  544.         scaled_capacity = (pdata->design_cap >> 1) +
  545.                                 (pdata->design_cap >> 3) +
  546.                                 (pdata->design_cap >> 4);
  547.  
  548.         /*
  549.          * bit 7 of cap1 register is set to indicate battery maximum
  550.          * capacity is valid
  551.          */
  552.         pdata->cdata.cap0 = scaled_capacity & 0xFF;
  553.         pdata->cdata.cap1 = (scaled_capacity >> 8) | 0x80;
  554.  
  555.         pdata->cdata.rdc1 = 0xc0;
  556.         pdata->cdata.rdc0 = 0x97;
  557.  
  558.         /* Donot update the entire fg  data on every boot*/
  559.         pdata->cdata.fco = 0x00;
  560.         /* copy curve data */
  561.         if (pdata->design_max_volt == 4200)
  562.                 fg_bat_curve = fg_bat_curve_4200mv;
  563.         else
  564.                 fg_bat_curve = fg_bat_curve_4350mv;
  565.  
  566.         for (i = 0; i < XPWR_BAT_CURVE_SIZE; i++)
  567.                 pdata->cdata.bat_curve[i] = fg_bat_curve[i];
  568.  
  569.         pdata->fg_save_restore_enabled = 0;
  570.         return;
  571. }
  572.  
  573. static void dc_xpwr_fg_pdata(void)
  574. {
  575.         static struct dollarcove_fg_pdata pdata;
  576.         int i, temp_mon_ranges;
  577.         int scaled_capacity;
  578.  
  579.         if (ps_batt_chrg_prof.chrg_prof_type == CHRG_PROF_NONE
  580.                 || (!pse_mod_prof))
  581.                 snprintf(pdata.battid, (BATTID_STR_LEN + 1),
  582.                         "%s", BATTID_UNKNOWN);
  583.         else {
  584.                 memcpy(pdata.battid, pse_mod_prof->batt_id,
  585.                                 strlen(pse_mod_prof->batt_id));
  586.                 pdata.battid[BATTID_STR_LEN] = '\0';
  587.         }
  588.  
  589.         platform_set_battery_data(&pdata, &ps_batt_chrg_prof);
  590.         pse_mod_prof = (struct ps_pse_mod_prof *)
  591.                                         ps_batt_chrg_prof.batt_prof;
  592.         temp_mon_ranges = min_t(u16, pse_mod_prof->temp_mon_ranges,
  593.                                                 BATT_TEMP_NR_RNG);
  594.         for (i = 0; i < temp_mon_ranges; ++i) {
  595.                 if (pse_mod_prof->temp_mon_range[i].full_chrg_cur)
  596.                                 break;
  597.         }
  598.         if (i < temp_mon_ranges)
  599.                 pdata.max_temp = pse_mod_prof->temp_mon_range[i].temp_up_lim;
  600.         else
  601.                 pdata.max_temp = XPOWER_DEFAULT_TEMP_MAX;
  602.  
  603.         pdata.min_temp = pse_mod_prof->temp_low_lim;
  604.  
  605.         /* Load FG config data to pdata */
  606.         dc_xpwr_get_fg_config_data(&pdata);
  607.  
  608.  
  609.         intel_soc_pmic_set_pdata("dollar_cove_battery",
  610.                                 (void *)&pdata, sizeof(pdata), 0);
  611. }
  612.  
  613. static void dc_xpwr_pwrsrc_pdata(void)
  614. {
  615.         static struct dc_xpwr_pwrsrc_pdata pdata;
  616.  
  617.         /*
  618.          * set en_chrg_det to true if the
  619.          * D+/D- lines are connected to
  620.          * PMIC itself.
  621.          */
  622.         pdata.en_chrg_det = true;
  623.  
  624.         /* Get the gpio based uab mux which will be used to switch usb D+/D-
  625.          * data line between SOC for data communication and PMIC for charger
  626.          * detection functionality.
  627.          */
  628.         pdata.gpio_mux_cntl = devm_gpiod_get_index(dollar_cove_pmic.dev,
  629.                                 "pmic_res", GPIO_USB_MUX_INDEX);
  630.         if (IS_ERR(pdata.gpio_mux_cntl))
  631.                 pdata.gpio_mux_cntl = NULL;
  632.         else
  633.                 gpiod_put(pdata.gpio_mux_cntl);
  634.  
  635.         intel_soc_pmic_set_pdata("dollar_cove_pwrsrc",
  636.                                  (void *)&pdata, sizeof(pdata), 0);
  637. }
  638.  
  639. static struct pmic_gpio_data dollar_cove_gpio_data = {
  640.         .type = DOLLAR_COVE,
  641.         .num_gpio = 2,
  642.         .num_vgpio = 0x5e,
  643. };
  644.  
  645. static void dc_set_gpio_pdata(void)
  646. {
  647.         intel_soc_pmic_set_pdata("dollar_cove_gpio",
  648.                                 (void *)&dollar_cove_gpio_data,
  649.                                 sizeof(dollar_cove_gpio_data), 0);
  650. }
  651.  
  652.  
  653. static int dollar_cove_init(void)
  654. {
  655.         pr_info("Dollar Cove: IC_TYPE 0x%02X\n", intel_soc_pmic_readb(0x03));
  656.         dc_xpwr_chrg_pdata();
  657.         dc_xpwr_pwrsrc_pdata();
  658.         dc_xpwr_fg_pdata();
  659.         dc_set_gpio_pdata();
  660.  
  661.         return 0;
  662. }
  663.  
  664. struct intel_soc_pmic dollar_cove_pmic = {
  665.         .label          = "dollar cove",
  666.         .irq_flags      = IRQF_TRIGGER_FALLING | IRQF_ONESHOT
  667.                                 | IRQF_NO_SUSPEND,
  668.         .init           = dollar_cove_init,
  669.         .cell_dev       = dollar_cove_dev,
  670.         .irq_regmap     = dollar_cove_irqregmap,
  671.         .irq_num        = 48,
  672. };
  673.  
  674. MODULE_LICENSE("GPL");
  675. MODULE_AUTHOR("Yang Bin <bin.yang@intel.com");
RAW Paste Data