13784b6d6SRobin Gong /* 23784b6d6SRobin Gong * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. 33784b6d6SRobin Gong * 43784b6d6SRobin Gong * This program is free software; you can redistribute it and/or modify 53784b6d6SRobin Gong * it under the terms of the GNU General Public License as published by 63784b6d6SRobin Gong * the Free Software Foundation; either version 2 of the License, or 73784b6d6SRobin Gong * (at your option) any later version. 83784b6d6SRobin Gong * 93784b6d6SRobin Gong * This program is distributed in the hope that it will be useful, 103784b6d6SRobin Gong * but WITHOUT ANY WARRANTY; without even the implied warranty of 113784b6d6SRobin Gong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 123784b6d6SRobin Gong * GNU General Public License for more details. 133784b6d6SRobin Gong * 143784b6d6SRobin Gong * You should have received a copy of the GNU General Public License 153784b6d6SRobin Gong * along with this program; if not, write to the Free Software 163784b6d6SRobin Gong * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 173784b6d6SRobin Gong */ 183784b6d6SRobin Gong #include <linux/kernel.h> 193784b6d6SRobin Gong #include <linux/module.h> 203784b6d6SRobin Gong #include <linux/init.h> 213784b6d6SRobin Gong #include <linux/err.h> 223784b6d6SRobin Gong #include <linux/of.h> 233784b6d6SRobin Gong #include <linux/of_device.h> 243784b6d6SRobin Gong #include <linux/regulator/of_regulator.h> 253784b6d6SRobin Gong #include <linux/platform_device.h> 263784b6d6SRobin Gong #include <linux/regulator/driver.h> 273784b6d6SRobin Gong #include <linux/regulator/machine.h> 283784b6d6SRobin Gong #include <linux/regulator/pfuze100.h> 293784b6d6SRobin Gong #include <linux/i2c.h> 303784b6d6SRobin Gong #include <linux/slab.h> 313784b6d6SRobin Gong #include <linux/regmap.h> 323784b6d6SRobin Gong 333784b6d6SRobin Gong #define PFUZE_NUMREGS 128 343784b6d6SRobin Gong #define PFUZE100_VOL_OFFSET 0 353784b6d6SRobin Gong #define PFUZE100_STANDBY_OFFSET 1 363784b6d6SRobin Gong #define PFUZE100_MODE_OFFSET 3 373784b6d6SRobin Gong #define PFUZE100_CONF_OFFSET 4 383784b6d6SRobin Gong 393784b6d6SRobin Gong #define PFUZE100_DEVICEID 0x0 403784b6d6SRobin Gong #define PFUZE100_REVID 0x3 41a1b6fa85SAxel Lin #define PFUZE100_FABID 0x4 423784b6d6SRobin Gong 433784b6d6SRobin Gong #define PFUZE100_SW1ABVOL 0x20 443784b6d6SRobin Gong #define PFUZE100_SW1CVOL 0x2e 453784b6d6SRobin Gong #define PFUZE100_SW2VOL 0x35 463784b6d6SRobin Gong #define PFUZE100_SW3AVOL 0x3c 473784b6d6SRobin Gong #define PFUZE100_SW3BVOL 0x43 483784b6d6SRobin Gong #define PFUZE100_SW4VOL 0x4a 493784b6d6SRobin Gong #define PFUZE100_SWBSTCON1 0x66 503784b6d6SRobin Gong #define PFUZE100_VREFDDRCON 0x6a 513784b6d6SRobin Gong #define PFUZE100_VSNVSVOL 0x6b 523784b6d6SRobin Gong #define PFUZE100_VGEN1VOL 0x6c 533784b6d6SRobin Gong #define PFUZE100_VGEN2VOL 0x6d 543784b6d6SRobin Gong #define PFUZE100_VGEN3VOL 0x6e 553784b6d6SRobin Gong #define PFUZE100_VGEN4VOL 0x6f 563784b6d6SRobin Gong #define PFUZE100_VGEN5VOL 0x70 573784b6d6SRobin Gong #define PFUZE100_VGEN6VOL 0x71 583784b6d6SRobin Gong 593784b6d6SRobin Gong struct pfuze_regulator { 603784b6d6SRobin Gong struct regulator_desc desc; 613784b6d6SRobin Gong unsigned char stby_reg; 623784b6d6SRobin Gong unsigned char stby_mask; 633784b6d6SRobin Gong }; 643784b6d6SRobin Gong 653784b6d6SRobin Gong struct pfuze_chip { 663784b6d6SRobin Gong struct regmap *regmap; 673784b6d6SRobin Gong struct device *dev; 683784b6d6SRobin Gong struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR]; 693784b6d6SRobin Gong struct regulator_dev *regulators[PFUZE100_MAX_REGULATOR]; 703784b6d6SRobin Gong }; 713784b6d6SRobin Gong 723784b6d6SRobin Gong static const int pfuze100_swbst[] = { 733784b6d6SRobin Gong 5000000, 5050000, 5100000, 5150000, 743784b6d6SRobin Gong }; 753784b6d6SRobin Gong 763784b6d6SRobin Gong static const int pfuze100_vsnvs[] = { 773784b6d6SRobin Gong 1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, 783784b6d6SRobin Gong }; 793784b6d6SRobin Gong 803784b6d6SRobin Gong static const struct i2c_device_id pfuze_device_id[] = { 813784b6d6SRobin Gong {.name = "pfuze100"}, 823784b6d6SRobin Gong {}, 833784b6d6SRobin Gong }; 843784b6d6SRobin Gong MODULE_DEVICE_TABLE(i2c, pfuze_device_id); 853784b6d6SRobin Gong 863784b6d6SRobin Gong static const struct of_device_id pfuze_dt_ids[] = { 873784b6d6SRobin Gong { .compatible = "fsl,pfuze100" }, 883784b6d6SRobin Gong {}, 893784b6d6SRobin Gong }; 903784b6d6SRobin Gong MODULE_DEVICE_TABLE(of, pfuze_dt_ids); 913784b6d6SRobin Gong 923784b6d6SRobin Gong static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) 933784b6d6SRobin Gong { 943784b6d6SRobin Gong struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); 953784b6d6SRobin Gong int id = rdev->desc->id; 96e5656669SAxel Lin unsigned int ramp_bits; 973784b6d6SRobin Gong int ret; 983784b6d6SRobin Gong 993784b6d6SRobin Gong if (id < PFUZE100_SWBST) { 100e5656669SAxel Lin ramp_delay = 12500 / ramp_delay; 1013784b6d6SRobin Gong ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3); 102e5656669SAxel Lin ret = regmap_update_bits(pfuze100->regmap, 103e5656669SAxel Lin rdev->desc->vsel_reg + 4, 104e5656669SAxel Lin 0xc0, ramp_bits << 6); 1053784b6d6SRobin Gong if (ret < 0) 1063784b6d6SRobin Gong dev_err(pfuze100->dev, "ramp failed, err %d\n", ret); 1073784b6d6SRobin Gong } else 1083784b6d6SRobin Gong ret = -EACCES; 1093784b6d6SRobin Gong 1103784b6d6SRobin Gong return ret; 1113784b6d6SRobin Gong } 1123784b6d6SRobin Gong 1133784b6d6SRobin Gong static struct regulator_ops pfuze100_ldo_regulator_ops = { 1143784b6d6SRobin Gong .enable = regulator_enable_regmap, 1153784b6d6SRobin Gong .disable = regulator_disable_regmap, 1163784b6d6SRobin Gong .is_enabled = regulator_is_enabled_regmap, 1173784b6d6SRobin Gong .list_voltage = regulator_list_voltage_linear, 1183784b6d6SRobin Gong .set_voltage_sel = regulator_set_voltage_sel_regmap, 1193784b6d6SRobin Gong .get_voltage_sel = regulator_get_voltage_sel_regmap, 1203784b6d6SRobin Gong }; 1213784b6d6SRobin Gong 1223784b6d6SRobin Gong static struct regulator_ops pfuze100_fixed_regulator_ops = { 1233784b6d6SRobin Gong .list_voltage = regulator_list_voltage_linear, 1243784b6d6SRobin Gong }; 1253784b6d6SRobin Gong 1263784b6d6SRobin Gong static struct regulator_ops pfuze100_sw_regulator_ops = { 1273784b6d6SRobin Gong .list_voltage = regulator_list_voltage_linear, 1283784b6d6SRobin Gong .set_voltage_sel = regulator_set_voltage_sel_regmap, 1293784b6d6SRobin Gong .get_voltage_sel = regulator_get_voltage_sel_regmap, 1303784b6d6SRobin Gong .set_voltage_time_sel = regulator_set_voltage_time_sel, 1313784b6d6SRobin Gong .set_ramp_delay = pfuze100_set_ramp_delay, 1323784b6d6SRobin Gong }; 1333784b6d6SRobin Gong 1343784b6d6SRobin Gong static struct regulator_ops pfuze100_swb_regulator_ops = { 1353784b6d6SRobin Gong .list_voltage = regulator_list_voltage_table, 1362e04cc41SAxel Lin .map_voltage = regulator_map_voltage_ascend, 1373784b6d6SRobin Gong .set_voltage_sel = regulator_set_voltage_sel_regmap, 1383784b6d6SRobin Gong .get_voltage_sel = regulator_get_voltage_sel_regmap, 1393784b6d6SRobin Gong 1403784b6d6SRobin Gong }; 1413784b6d6SRobin Gong 1423784b6d6SRobin Gong #define PFUZE100_FIXED_REG(_name, base, voltage) \ 1433784b6d6SRobin Gong [PFUZE100_ ## _name] = { \ 1443784b6d6SRobin Gong .desc = { \ 1453784b6d6SRobin Gong .name = #_name, \ 1463784b6d6SRobin Gong .n_voltages = 1, \ 1473784b6d6SRobin Gong .ops = &pfuze100_fixed_regulator_ops, \ 1483784b6d6SRobin Gong .type = REGULATOR_VOLTAGE, \ 1493784b6d6SRobin Gong .id = PFUZE100_ ## _name, \ 1503784b6d6SRobin Gong .owner = THIS_MODULE, \ 1513784b6d6SRobin Gong .min_uV = (voltage), \ 1523784b6d6SRobin Gong .enable_reg = (base), \ 1533784b6d6SRobin Gong .enable_mask = 0x10, \ 1543784b6d6SRobin Gong }, \ 1553784b6d6SRobin Gong } 1563784b6d6SRobin Gong 1573784b6d6SRobin Gong #define PFUZE100_SW_REG(_name, base, min, max, step) \ 1583784b6d6SRobin Gong [PFUZE100_ ## _name] = { \ 1593784b6d6SRobin Gong .desc = { \ 1603784b6d6SRobin Gong .name = #_name,\ 1613784b6d6SRobin Gong .n_voltages = ((max) - (min)) / (step) + 1, \ 1623784b6d6SRobin Gong .ops = &pfuze100_sw_regulator_ops, \ 1633784b6d6SRobin Gong .type = REGULATOR_VOLTAGE, \ 1643784b6d6SRobin Gong .id = PFUZE100_ ## _name, \ 1653784b6d6SRobin Gong .owner = THIS_MODULE, \ 1663784b6d6SRobin Gong .min_uV = (min), \ 1673784b6d6SRobin Gong .uV_step = (step), \ 1683784b6d6SRobin Gong .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ 1693784b6d6SRobin Gong .vsel_mask = 0x3f, \ 1703784b6d6SRobin Gong }, \ 1713784b6d6SRobin Gong .stby_reg = (base) + PFUZE100_STANDBY_OFFSET, \ 1723784b6d6SRobin Gong .stby_mask = 0x3f, \ 1733784b6d6SRobin Gong } 1743784b6d6SRobin Gong 1753784b6d6SRobin Gong #define PFUZE100_SWB_REG(_name, base, mask, voltages) \ 1763784b6d6SRobin Gong [PFUZE100_ ## _name] = { \ 1773784b6d6SRobin Gong .desc = { \ 1783784b6d6SRobin Gong .name = #_name, \ 1793784b6d6SRobin Gong .n_voltages = ARRAY_SIZE(voltages), \ 1803784b6d6SRobin Gong .ops = &pfuze100_swb_regulator_ops, \ 1813784b6d6SRobin Gong .type = REGULATOR_VOLTAGE, \ 1823784b6d6SRobin Gong .id = PFUZE100_ ## _name, \ 1833784b6d6SRobin Gong .owner = THIS_MODULE, \ 1843784b6d6SRobin Gong .volt_table = voltages, \ 1853784b6d6SRobin Gong .vsel_reg = (base), \ 1863784b6d6SRobin Gong .vsel_mask = (mask), \ 1873784b6d6SRobin Gong }, \ 1883784b6d6SRobin Gong } 1893784b6d6SRobin Gong 1903784b6d6SRobin Gong #define PFUZE100_VGEN_REG(_name, base, min, max, step) \ 1913784b6d6SRobin Gong [PFUZE100_ ## _name] = { \ 1923784b6d6SRobin Gong .desc = { \ 1933784b6d6SRobin Gong .name = #_name, \ 1943784b6d6SRobin Gong .n_voltages = ((max) - (min)) / (step) + 1, \ 1953784b6d6SRobin Gong .ops = &pfuze100_ldo_regulator_ops, \ 1963784b6d6SRobin Gong .type = REGULATOR_VOLTAGE, \ 1973784b6d6SRobin Gong .id = PFUZE100_ ## _name, \ 1983784b6d6SRobin Gong .owner = THIS_MODULE, \ 1993784b6d6SRobin Gong .min_uV = (min), \ 2003784b6d6SRobin Gong .uV_step = (step), \ 2013784b6d6SRobin Gong .vsel_reg = (base), \ 2023784b6d6SRobin Gong .vsel_mask = 0xf, \ 2033784b6d6SRobin Gong .enable_reg = (base), \ 2043784b6d6SRobin Gong .enable_mask = 0x10, \ 2053784b6d6SRobin Gong }, \ 2063784b6d6SRobin Gong .stby_reg = (base), \ 2073784b6d6SRobin Gong .stby_mask = 0x20, \ 2083784b6d6SRobin Gong } 2093784b6d6SRobin Gong 2103784b6d6SRobin Gong static struct pfuze_regulator pfuze100_regulators[] = { 2113784b6d6SRobin Gong PFUZE100_SW_REG(SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000), 2123784b6d6SRobin Gong PFUZE100_SW_REG(SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000), 2133784b6d6SRobin Gong PFUZE100_SW_REG(SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000), 2143784b6d6SRobin Gong PFUZE100_SW_REG(SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000), 2153784b6d6SRobin Gong PFUZE100_SW_REG(SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000), 2163784b6d6SRobin Gong PFUZE100_SW_REG(SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000), 2173784b6d6SRobin Gong PFUZE100_SWB_REG(SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst), 2183784b6d6SRobin Gong PFUZE100_SWB_REG(VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), 2193784b6d6SRobin Gong PFUZE100_FIXED_REG(VREFDDR, PFUZE100_VREFDDRCON, 750000), 2203784b6d6SRobin Gong PFUZE100_VGEN_REG(VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000), 2213784b6d6SRobin Gong PFUZE100_VGEN_REG(VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000), 2223784b6d6SRobin Gong PFUZE100_VGEN_REG(VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000), 2233784b6d6SRobin Gong PFUZE100_VGEN_REG(VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000), 2243784b6d6SRobin Gong PFUZE100_VGEN_REG(VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000), 2253784b6d6SRobin Gong PFUZE100_VGEN_REG(VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), 2263784b6d6SRobin Gong }; 2273784b6d6SRobin Gong 2283784b6d6SRobin Gong #ifdef CONFIG_OF 2293784b6d6SRobin Gong static struct of_regulator_match pfuze100_matches[] = { 2303784b6d6SRobin Gong { .name = "sw1ab", }, 2313784b6d6SRobin Gong { .name = "sw1c", }, 2323784b6d6SRobin Gong { .name = "sw2", }, 2333784b6d6SRobin Gong { .name = "sw3a", }, 2343784b6d6SRobin Gong { .name = "sw3b", }, 2353784b6d6SRobin Gong { .name = "sw4", }, 2363784b6d6SRobin Gong { .name = "swbst", }, 2373784b6d6SRobin Gong { .name = "vsnvs", }, 2383784b6d6SRobin Gong { .name = "vrefddr", }, 2393784b6d6SRobin Gong { .name = "vgen1", }, 2403784b6d6SRobin Gong { .name = "vgen2", }, 2413784b6d6SRobin Gong { .name = "vgen3", }, 2423784b6d6SRobin Gong { .name = "vgen4", }, 2433784b6d6SRobin Gong { .name = "vgen5", }, 2443784b6d6SRobin Gong { .name = "vgen6", }, 2453784b6d6SRobin Gong }; 2463784b6d6SRobin Gong 2473784b6d6SRobin Gong static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) 2483784b6d6SRobin Gong { 2493784b6d6SRobin Gong struct device *dev = chip->dev; 2503784b6d6SRobin Gong struct device_node *np, *parent; 2513784b6d6SRobin Gong int ret; 2523784b6d6SRobin Gong 2533e01c75aSFabio Estevam np = of_node_get(dev->of_node); 2543784b6d6SRobin Gong if (!np) 255*6428789eSFabio Estevam return -EINVAL; 2563784b6d6SRobin Gong 257d7857c42SSachin Kamat parent = of_get_child_by_name(np, "regulators"); 2583784b6d6SRobin Gong if (!parent) { 2593784b6d6SRobin Gong dev_err(dev, "regulators node not found\n"); 2603784b6d6SRobin Gong return -EINVAL; 2613784b6d6SRobin Gong } 2623784b6d6SRobin Gong 2633784b6d6SRobin Gong ret = of_regulator_match(dev, parent, pfuze100_matches, 2643784b6d6SRobin Gong ARRAY_SIZE(pfuze100_matches)); 2653784b6d6SRobin Gong 2663784b6d6SRobin Gong of_node_put(parent); 2673784b6d6SRobin Gong if (ret < 0) { 2683784b6d6SRobin Gong dev_err(dev, "Error parsing regulator init data: %d\n", 2693784b6d6SRobin Gong ret); 2703784b6d6SRobin Gong return ret; 2713784b6d6SRobin Gong } 2723784b6d6SRobin Gong 2733784b6d6SRobin Gong return 0; 2743784b6d6SRobin Gong } 2753784b6d6SRobin Gong 2763784b6d6SRobin Gong static inline struct regulator_init_data *match_init_data(int index) 2773784b6d6SRobin Gong { 2783784b6d6SRobin Gong return pfuze100_matches[index].init_data; 2793784b6d6SRobin Gong } 2803784b6d6SRobin Gong 2813784b6d6SRobin Gong static inline struct device_node *match_of_node(int index) 2823784b6d6SRobin Gong { 2833784b6d6SRobin Gong return pfuze100_matches[index].of_node; 2843784b6d6SRobin Gong } 2853784b6d6SRobin Gong #else 2863784b6d6SRobin Gong static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) 2873784b6d6SRobin Gong { 288205c97bcSRobin Gong return 0; 2893784b6d6SRobin Gong } 2903784b6d6SRobin Gong 2913784b6d6SRobin Gong static inline struct regulator_init_data *match_init_data(int index) 2923784b6d6SRobin Gong { 2933784b6d6SRobin Gong return NULL; 2943784b6d6SRobin Gong } 2953784b6d6SRobin Gong 2963784b6d6SRobin Gong static inline struct device_node *match_of_node(int index) 2973784b6d6SRobin Gong { 2983784b6d6SRobin Gong return NULL; 2993784b6d6SRobin Gong } 3003784b6d6SRobin Gong #endif 3013784b6d6SRobin Gong 3023784b6d6SRobin Gong static int pfuze_identify(struct pfuze_chip *pfuze_chip) 3033784b6d6SRobin Gong { 3043784b6d6SRobin Gong unsigned int value; 3053784b6d6SRobin Gong int ret; 3063784b6d6SRobin Gong 3073784b6d6SRobin Gong ret = regmap_read(pfuze_chip->regmap, PFUZE100_DEVICEID, &value); 3083784b6d6SRobin Gong if (ret) 3093784b6d6SRobin Gong return ret; 3103784b6d6SRobin Gong 311236c427cSTim Harvey switch (value & 0x0f) { 31262b38916SFabio Estevam /* 31362b38916SFabio Estevam * Freescale misprogrammed 1-3% of parts prior to week 8 of 2013 31462b38916SFabio Estevam * as ID=8 31562b38916SFabio Estevam */ 316236c427cSTim Harvey case 0x8: 317236c427cSTim Harvey dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8"); 318236c427cSTim Harvey case 0x0: 319236c427cSTim Harvey break; 320236c427cSTim Harvey default: 3213784b6d6SRobin Gong dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value); 3223784b6d6SRobin Gong return -ENODEV; 3233784b6d6SRobin Gong } 3243784b6d6SRobin Gong 3253784b6d6SRobin Gong ret = regmap_read(pfuze_chip->regmap, PFUZE100_REVID, &value); 3263784b6d6SRobin Gong if (ret) 3273784b6d6SRobin Gong return ret; 3283784b6d6SRobin Gong dev_info(pfuze_chip->dev, 329f2694383SFabio Estevam "Full layer: %x, Metal layer: %x\n", 3303784b6d6SRobin Gong (value & 0xf0) >> 4, value & 0x0f); 3313784b6d6SRobin Gong 3323784b6d6SRobin Gong ret = regmap_read(pfuze_chip->regmap, PFUZE100_FABID, &value); 3333784b6d6SRobin Gong if (ret) 3343784b6d6SRobin Gong return ret; 3353784b6d6SRobin Gong dev_info(pfuze_chip->dev, "FAB: %x, FIN: %x\n", 3363784b6d6SRobin Gong (value & 0xc) >> 2, value & 0x3); 3373784b6d6SRobin Gong 3383784b6d6SRobin Gong return 0; 3393784b6d6SRobin Gong } 3403784b6d6SRobin Gong 3413784b6d6SRobin Gong static const struct regmap_config pfuze_regmap_config = { 3423784b6d6SRobin Gong .reg_bits = 8, 3433784b6d6SRobin Gong .val_bits = 8, 3446b8430c3SAxel Lin .max_register = PFUZE_NUMREGS - 1, 3453784b6d6SRobin Gong .cache_type = REGCACHE_RBTREE, 3463784b6d6SRobin Gong }; 3473784b6d6SRobin Gong 3483784b6d6SRobin Gong static int pfuze100_regulator_probe(struct i2c_client *client, 3493784b6d6SRobin Gong const struct i2c_device_id *id) 3503784b6d6SRobin Gong { 3513784b6d6SRobin Gong struct pfuze_chip *pfuze_chip; 3523784b6d6SRobin Gong struct pfuze_regulator_platform_data *pdata = 3533784b6d6SRobin Gong dev_get_platdata(&client->dev); 3543784b6d6SRobin Gong struct regulator_config config = { }; 3553784b6d6SRobin Gong int i, ret; 3563784b6d6SRobin Gong 3573784b6d6SRobin Gong pfuze_chip = devm_kzalloc(&client->dev, sizeof(*pfuze_chip), 3583784b6d6SRobin Gong GFP_KERNEL); 3593784b6d6SRobin Gong if (!pfuze_chip) 3603784b6d6SRobin Gong return -ENOMEM; 3613784b6d6SRobin Gong 3628c86ab25SAxel Lin i2c_set_clientdata(client, pfuze_chip); 3633784b6d6SRobin Gong 3643784b6d6SRobin Gong memcpy(pfuze_chip->regulator_descs, pfuze100_regulators, 3653784b6d6SRobin Gong sizeof(pfuze_chip->regulator_descs)); 3663784b6d6SRobin Gong 3673784b6d6SRobin Gong pfuze_chip->dev = &client->dev; 3683784b6d6SRobin Gong 3693784b6d6SRobin Gong pfuze_chip->regmap = devm_regmap_init_i2c(client, &pfuze_regmap_config); 3703784b6d6SRobin Gong if (IS_ERR(pfuze_chip->regmap)) { 3713784b6d6SRobin Gong ret = PTR_ERR(pfuze_chip->regmap); 3723784b6d6SRobin Gong dev_err(&client->dev, 3733784b6d6SRobin Gong "regmap allocation failed with err %d\n", ret); 3743784b6d6SRobin Gong return ret; 3753784b6d6SRobin Gong } 3763784b6d6SRobin Gong 3773784b6d6SRobin Gong ret = pfuze_identify(pfuze_chip); 3783784b6d6SRobin Gong if (ret) { 3793784b6d6SRobin Gong dev_err(&client->dev, "unrecognized pfuze chip ID!\n"); 3803784b6d6SRobin Gong return ret; 3813784b6d6SRobin Gong } 3823784b6d6SRobin Gong 3833784b6d6SRobin Gong ret = pfuze_parse_regulators_dt(pfuze_chip); 3843784b6d6SRobin Gong if (ret) 3853784b6d6SRobin Gong return ret; 3863784b6d6SRobin Gong 3873784b6d6SRobin Gong for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) { 3883784b6d6SRobin Gong struct regulator_init_data *init_data; 389d9493234SAxel Lin struct regulator_desc *desc; 3903784b6d6SRobin Gong int val; 3913784b6d6SRobin Gong 392d9493234SAxel Lin desc = &pfuze_chip->regulator_descs[i].desc; 393d9493234SAxel Lin 3943784b6d6SRobin Gong if (pdata) 3953784b6d6SRobin Gong init_data = pdata->init_data[i]; 3963784b6d6SRobin Gong else 3973784b6d6SRobin Gong init_data = match_init_data(i); 3983784b6d6SRobin Gong 3993784b6d6SRobin Gong /* SW2~SW4 high bit check and modify the voltage value table */ 4003784b6d6SRobin Gong if (i > PFUZE100_SW1C && i < PFUZE100_SWBST) { 401d9493234SAxel Lin regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); 4023784b6d6SRobin Gong if (val & 0x40) { 403d9493234SAxel Lin desc->min_uV = 800000; 404d9493234SAxel Lin desc->uV_step = 50000; 405d9493234SAxel Lin desc->n_voltages = 51; 4063784b6d6SRobin Gong } 4073784b6d6SRobin Gong } 4083784b6d6SRobin Gong 4093784b6d6SRobin Gong config.dev = &client->dev; 4103784b6d6SRobin Gong config.init_data = init_data; 4113784b6d6SRobin Gong config.driver_data = pfuze_chip; 4123784b6d6SRobin Gong config.of_node = match_of_node(i); 4133784b6d6SRobin Gong 414f5247b40SJingoo Han pfuze_chip->regulators[i] = 415f5247b40SJingoo Han devm_regulator_register(&client->dev, desc, &config); 4163784b6d6SRobin Gong if (IS_ERR(pfuze_chip->regulators[i])) { 4173784b6d6SRobin Gong dev_err(&client->dev, "register regulator%s failed\n", 4183784b6d6SRobin Gong pfuze100_regulators[i].desc.name); 419f5247b40SJingoo Han return PTR_ERR(pfuze_chip->regulators[i]); 4203784b6d6SRobin Gong } 4213784b6d6SRobin Gong } 4223784b6d6SRobin Gong 4233784b6d6SRobin Gong return 0; 4243784b6d6SRobin Gong } 4253784b6d6SRobin Gong 4263784b6d6SRobin Gong static struct i2c_driver pfuze_driver = { 4273784b6d6SRobin Gong .id_table = pfuze_device_id, 4283784b6d6SRobin Gong .driver = { 4293784b6d6SRobin Gong .name = "pfuze100-regulator", 4303784b6d6SRobin Gong .owner = THIS_MODULE, 4313784b6d6SRobin Gong .of_match_table = pfuze_dt_ids, 4323784b6d6SRobin Gong }, 4333784b6d6SRobin Gong .probe = pfuze100_regulator_probe, 4343784b6d6SRobin Gong }; 4353784b6d6SRobin Gong module_i2c_driver(pfuze_driver); 4363784b6d6SRobin Gong 4373784b6d6SRobin Gong MODULE_AUTHOR("Robin Gong <b38343@freescale.com>"); 4383784b6d6SRobin Gong MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC"); 43912d20fc2SRobin Gong MODULE_LICENSE("GPL v2"); 44040839bffSAxel Lin MODULE_ALIAS("i2c:pfuze100-regulator"); 441