162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// Regulator Driver for Freescale MC13892 PMIC 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright 2010 Yong Shen <yong.shen@linaro.org> 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/mfd/mc13892.h> 1062306a36Sopenharmony_ci#include <linux/regulator/machine.h> 1162306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/err.h> 1762306a36Sopenharmony_ci#include <linux/module.h> 1862306a36Sopenharmony_ci#include "mc13xxx.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define MC13892_REVISION 7 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define MC13892_POWERCTL0 13 2362306a36Sopenharmony_ci#define MC13892_POWERCTL0_USEROFFSPI 3 2462306a36Sopenharmony_ci#define MC13892_POWERCTL0_VCOINCELLVSEL 20 2562306a36Sopenharmony_ci#define MC13892_POWERCTL0_VCOINCELLVSEL_M (7<<20) 2662306a36Sopenharmony_ci#define MC13892_POWERCTL0_VCOINCELLEN (1<<23) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define MC13892_SWITCHERS0_SWxHI (1<<23) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define MC13892_SWITCHERS0 24 3162306a36Sopenharmony_ci#define MC13892_SWITCHERS0_SW1VSEL 0 3262306a36Sopenharmony_ci#define MC13892_SWITCHERS0_SW1VSEL_M (0x1f<<0) 3362306a36Sopenharmony_ci#define MC13892_SWITCHERS0_SW1HI (1<<23) 3462306a36Sopenharmony_ci#define MC13892_SWITCHERS0_SW1EN 0 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define MC13892_SWITCHERS1 25 3762306a36Sopenharmony_ci#define MC13892_SWITCHERS1_SW2VSEL 0 3862306a36Sopenharmony_ci#define MC13892_SWITCHERS1_SW2VSEL_M (0x1f<<0) 3962306a36Sopenharmony_ci#define MC13892_SWITCHERS1_SW2HI (1<<23) 4062306a36Sopenharmony_ci#define MC13892_SWITCHERS1_SW2EN 0 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define MC13892_SWITCHERS2 26 4362306a36Sopenharmony_ci#define MC13892_SWITCHERS2_SW3VSEL 0 4462306a36Sopenharmony_ci#define MC13892_SWITCHERS2_SW3VSEL_M (0x1f<<0) 4562306a36Sopenharmony_ci#define MC13892_SWITCHERS2_SW3HI (1<<23) 4662306a36Sopenharmony_ci#define MC13892_SWITCHERS2_SW3EN 0 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define MC13892_SWITCHERS3 27 4962306a36Sopenharmony_ci#define MC13892_SWITCHERS3_SW4VSEL 0 5062306a36Sopenharmony_ci#define MC13892_SWITCHERS3_SW4VSEL_M (0x1f<<0) 5162306a36Sopenharmony_ci#define MC13892_SWITCHERS3_SW4HI (1<<23) 5262306a36Sopenharmony_ci#define MC13892_SWITCHERS3_SW4EN 0 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define MC13892_SWITCHERS4 28 5562306a36Sopenharmony_ci#define MC13892_SWITCHERS4_SW1MODE 0 5662306a36Sopenharmony_ci#define MC13892_SWITCHERS4_SW1MODE_AUTO (8<<0) 5762306a36Sopenharmony_ci#define MC13892_SWITCHERS4_SW1MODE_M (0xf<<0) 5862306a36Sopenharmony_ci#define MC13892_SWITCHERS4_SW2MODE 10 5962306a36Sopenharmony_ci#define MC13892_SWITCHERS4_SW2MODE_AUTO (8<<10) 6062306a36Sopenharmony_ci#define MC13892_SWITCHERS4_SW2MODE_M (0xf<<10) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define MC13892_SWITCHERS5 29 6362306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SW3MODE 0 6462306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SW3MODE_AUTO (8<<0) 6562306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SW3MODE_M (0xf<<0) 6662306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SW4MODE 8 6762306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SW4MODE_AUTO (8<<8) 6862306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SW4MODE_M (0xf<<8) 6962306a36Sopenharmony_ci#define MC13892_SWITCHERS5_SWBSTEN (1<<20) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0 30 7262306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN1VSEL 0 7362306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VDIGVSEL 4 7462306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN2VSEL 6 7562306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VPLLVSEL 9 7662306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VUSB2VSEL 11 7762306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN3VSEL 14 7862306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VCAMVSEL 16 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN1VSEL_M (3<<0) 8162306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VDIGVSEL_M (3<<4) 8262306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN2VSEL_M (7<<6) 8362306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VPLLVSEL_M (3<<9) 8462306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VUSB2VSEL_M (3<<11) 8562306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN3VSEL_M (1<<14) 8662306a36Sopenharmony_ci#define MC13892_REGULATORSETTING0_VCAMVSEL_M (3<<16) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1 31 8962306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1_VVIDEOVSEL 2 9062306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1_VAUDIOVSEL 4 9162306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1_VSDVSEL 6 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1_VVIDEOVSEL_M (3<<2) 9462306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1_VAUDIOVSEL_M (3<<4) 9562306a36Sopenharmony_ci#define MC13892_REGULATORSETTING1_VSDVSEL_M (7<<6) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define MC13892_REGULATORMODE0 32 9862306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN1EN (1<<0) 9962306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN1STDBY (1<<1) 10062306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN1MODE (1<<2) 10162306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VIOHIEN (1<<3) 10262306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VIOHISTDBY (1<<4) 10362306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VIOHIMODE (1<<5) 10462306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VDIGEN (1<<9) 10562306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VDIGSTDBY (1<<10) 10662306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VDIGMODE (1<<11) 10762306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN2EN (1<<12) 10862306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN2STDBY (1<<13) 10962306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN2MODE (1<<14) 11062306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VPLLEN (1<<15) 11162306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VPLLSTDBY (1<<16) 11262306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VPLLMODE (1<<17) 11362306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VUSB2EN (1<<18) 11462306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VUSB2STDBY (1<<19) 11562306a36Sopenharmony_ci#define MC13892_REGULATORMODE0_VUSB2MODE (1<<20) 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define MC13892_REGULATORMODE1 33 11862306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VGEN3EN (1<<0) 11962306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VGEN3STDBY (1<<1) 12062306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VGEN3MODE (1<<2) 12162306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMEN (1<<6) 12262306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMSTDBY (1<<7) 12362306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMMODE (1<<8) 12462306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMCONFIGEN (1<<9) 12562306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VVIDEOEN (1<<12) 12662306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VVIDEOSTDBY (1<<13) 12762306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VVIDEOMODE (1<<14) 12862306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VAUDIOEN (1<<15) 12962306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VAUDIOSTDBY (1<<16) 13062306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VAUDIOMODE (1<<17) 13162306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VSDEN (1<<18) 13262306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VSDSTDBY (1<<19) 13362306a36Sopenharmony_ci#define MC13892_REGULATORMODE1_VSDMODE (1<<20) 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#define MC13892_POWERMISC 34 13662306a36Sopenharmony_ci#define MC13892_POWERMISC_GPO1EN (1<<6) 13762306a36Sopenharmony_ci#define MC13892_POWERMISC_GPO2EN (1<<8) 13862306a36Sopenharmony_ci#define MC13892_POWERMISC_GPO3EN (1<<10) 13962306a36Sopenharmony_ci#define MC13892_POWERMISC_GPO4EN (1<<12) 14062306a36Sopenharmony_ci#define MC13892_POWERMISC_PWGT1SPIEN (1<<15) 14162306a36Sopenharmony_ci#define MC13892_POWERMISC_PWGT2SPIEN (1<<16) 14262306a36Sopenharmony_ci#define MC13892_POWERMISC_GPO4ADINEN (1<<21) 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#define MC13892_POWERMISC_PWGTSPI_M (3 << 15) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define MC13892_USB1 50 14762306a36Sopenharmony_ci#define MC13892_USB1_VUSBEN (1<<3) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const unsigned int mc13892_vcoincell[] = { 15062306a36Sopenharmony_ci 2500000, 2700000, 2800000, 2900000, 3000000, 3100000, 15162306a36Sopenharmony_ci 3200000, 3300000, 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic const unsigned int mc13892_sw1[] = { 15562306a36Sopenharmony_ci 600000, 625000, 650000, 675000, 700000, 725000, 15662306a36Sopenharmony_ci 750000, 775000, 800000, 825000, 850000, 875000, 15762306a36Sopenharmony_ci 900000, 925000, 950000, 975000, 1000000, 1025000, 15862306a36Sopenharmony_ci 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 15962306a36Sopenharmony_ci 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 16062306a36Sopenharmony_ci 1350000, 1375000 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/* 16462306a36Sopenharmony_ci * Note: this table is used to derive SWxVSEL by index into 16562306a36Sopenharmony_ci * the array. Offset the values by the index of 1100000uV 16662306a36Sopenharmony_ci * to get the actual register value for that voltage selector 16762306a36Sopenharmony_ci * if the HI bit is to be set as well. 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_ci#define MC13892_SWxHI_SEL_OFFSET 20 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic const unsigned int mc13892_sw[] = { 17262306a36Sopenharmony_ci 600000, 625000, 650000, 675000, 700000, 725000, 17362306a36Sopenharmony_ci 750000, 775000, 800000, 825000, 850000, 875000, 17462306a36Sopenharmony_ci 900000, 925000, 950000, 975000, 1000000, 1025000, 17562306a36Sopenharmony_ci 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 17662306a36Sopenharmony_ci 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 17762306a36Sopenharmony_ci 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 17862306a36Sopenharmony_ci 1500000, 1525000, 1550000, 1575000, 1600000, 1625000, 17962306a36Sopenharmony_ci 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 18062306a36Sopenharmony_ci 1800000, 1825000, 1850000, 1875000 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic const unsigned int mc13892_swbst[] = { 18462306a36Sopenharmony_ci 5000000, 18562306a36Sopenharmony_ci}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic const unsigned int mc13892_viohi[] = { 18862306a36Sopenharmony_ci 2775000, 18962306a36Sopenharmony_ci}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic const unsigned int mc13892_vpll[] = { 19262306a36Sopenharmony_ci 1050000, 1250000, 1650000, 1800000, 19362306a36Sopenharmony_ci}; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic const unsigned int mc13892_vdig[] = { 19662306a36Sopenharmony_ci 1050000, 1250000, 1650000, 1800000, 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic const unsigned int mc13892_vsd[] = { 20062306a36Sopenharmony_ci 1800000, 2000000, 2600000, 2700000, 20162306a36Sopenharmony_ci 2800000, 2900000, 3000000, 3150000, 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic const unsigned int mc13892_vusb2[] = { 20562306a36Sopenharmony_ci 2400000, 2600000, 2700000, 2775000, 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic const unsigned int mc13892_vvideo[] = { 20962306a36Sopenharmony_ci 2700000, 2775000, 2500000, 2600000, 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const unsigned int mc13892_vaudio[] = { 21362306a36Sopenharmony_ci 2300000, 2500000, 2775000, 3000000, 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic const unsigned int mc13892_vcam[] = { 21762306a36Sopenharmony_ci 2500000, 2600000, 2750000, 3000000, 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic const unsigned int mc13892_vgen1[] = { 22162306a36Sopenharmony_ci 1200000, 1500000, 2775000, 3150000, 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic const unsigned int mc13892_vgen2[] = { 22562306a36Sopenharmony_ci 1200000, 1500000, 1600000, 1800000, 22662306a36Sopenharmony_ci 2700000, 2800000, 3000000, 3150000, 22762306a36Sopenharmony_ci}; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic const unsigned int mc13892_vgen3[] = { 23062306a36Sopenharmony_ci 1800000, 2900000, 23162306a36Sopenharmony_ci}; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic const unsigned int mc13892_vusb[] = { 23462306a36Sopenharmony_ci 3300000, 23562306a36Sopenharmony_ci}; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic const unsigned int mc13892_gpo[] = { 23862306a36Sopenharmony_ci 2750000, 23962306a36Sopenharmony_ci}; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic const unsigned int mc13892_pwgtdrv[] = { 24262306a36Sopenharmony_ci 5000000, 24362306a36Sopenharmony_ci}; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic const struct regulator_ops mc13892_gpo_regulator_ops; 24662306a36Sopenharmony_cistatic const struct regulator_ops mc13892_sw_regulator_ops; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci#define MC13892_FIXED_DEFINE(name, node, reg, voltages) \ 25062306a36Sopenharmony_ci MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages, \ 25162306a36Sopenharmony_ci mc13xxx_fixed_regulator_ops) 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci#define MC13892_GPO_DEFINE(name, node, reg, voltages) \ 25462306a36Sopenharmony_ci MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages, \ 25562306a36Sopenharmony_ci mc13892_gpo_regulator_ops) 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci#define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages) \ 25862306a36Sopenharmony_ci MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ 25962306a36Sopenharmony_ci mc13892_sw_regulator_ops) 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci#define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages) \ 26262306a36Sopenharmony_ci MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ 26362306a36Sopenharmony_ci mc13xxx_regulator_ops) 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic struct mc13xxx_regulator mc13892_regulators[] = { 26662306a36Sopenharmony_ci MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell), 26762306a36Sopenharmony_ci MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1), 26862306a36Sopenharmony_ci MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw), 26962306a36Sopenharmony_ci MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw), 27062306a36Sopenharmony_ci MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw), 27162306a36Sopenharmony_ci MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst), 27262306a36Sopenharmony_ci MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi), 27362306a36Sopenharmony_ci MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0, 27462306a36Sopenharmony_ci mc13892_vpll), 27562306a36Sopenharmony_ci MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0, 27662306a36Sopenharmony_ci mc13892_vdig), 27762306a36Sopenharmony_ci MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1, 27862306a36Sopenharmony_ci mc13892_vsd), 27962306a36Sopenharmony_ci MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0, 28062306a36Sopenharmony_ci mc13892_vusb2), 28162306a36Sopenharmony_ci MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1, 28262306a36Sopenharmony_ci mc13892_vvideo), 28362306a36Sopenharmony_ci MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1, 28462306a36Sopenharmony_ci mc13892_vaudio), 28562306a36Sopenharmony_ci MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0, 28662306a36Sopenharmony_ci mc13892_vcam), 28762306a36Sopenharmony_ci MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0, 28862306a36Sopenharmony_ci mc13892_vgen1), 28962306a36Sopenharmony_ci MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0, 29062306a36Sopenharmony_ci mc13892_vgen2), 29162306a36Sopenharmony_ci MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0, 29262306a36Sopenharmony_ci mc13892_vgen3), 29362306a36Sopenharmony_ci MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb), 29462306a36Sopenharmony_ci MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo), 29562306a36Sopenharmony_ci MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo), 29662306a36Sopenharmony_ci MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo), 29762306a36Sopenharmony_ci MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo), 29862306a36Sopenharmony_ci MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv), 29962306a36Sopenharmony_ci MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv), 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, 30362306a36Sopenharmony_ci u32 val) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci struct mc13xxx *mc13892 = priv->mc13xxx; 30662306a36Sopenharmony_ci int ret; 30762306a36Sopenharmony_ci u32 valread; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci BUG_ON(val & ~mask); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 31262306a36Sopenharmony_ci ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread); 31362306a36Sopenharmony_ci if (ret) 31462306a36Sopenharmony_ci goto out; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* Update the stored state for Power Gates. */ 31762306a36Sopenharmony_ci priv->powermisc_pwgt_state = 31862306a36Sopenharmony_ci (priv->powermisc_pwgt_state & ~mask) | val; 31962306a36Sopenharmony_ci priv->powermisc_pwgt_state &= MC13892_POWERMISC_PWGTSPI_M; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* Construct the new register value */ 32262306a36Sopenharmony_ci valread = (valread & ~mask) | val; 32362306a36Sopenharmony_ci /* Overwrite the PWGTxEN with the stored version */ 32462306a36Sopenharmony_ci valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) | 32562306a36Sopenharmony_ci priv->powermisc_pwgt_state; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); 32862306a36Sopenharmony_ciout: 32962306a36Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 33062306a36Sopenharmony_ci return ret; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 33662306a36Sopenharmony_ci int id = rdev_get_id(rdev); 33762306a36Sopenharmony_ci u32 en_val = mc13892_regulators[id].enable_bit; 33862306a36Sopenharmony_ci u32 mask = mc13892_regulators[id].enable_bit; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* Power Gate enable value is 0 */ 34362306a36Sopenharmony_ci if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) 34462306a36Sopenharmony_ci en_val = 0; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (id == MC13892_GPO4) 34762306a36Sopenharmony_ci mask |= MC13892_POWERMISC_GPO4ADINEN; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci return mc13892_powermisc_rmw(priv, mask, en_val); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 35562306a36Sopenharmony_ci int id = rdev_get_id(rdev); 35662306a36Sopenharmony_ci u32 dis_val = 0; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci /* Power Gate disable value is 1 */ 36162306a36Sopenharmony_ci if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) 36262306a36Sopenharmony_ci dis_val = mc13892_regulators[id].enable_bit; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, 36562306a36Sopenharmony_ci dis_val); 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 37162306a36Sopenharmony_ci int ret, id = rdev_get_id(rdev); 37262306a36Sopenharmony_ci unsigned int val; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 37562306a36Sopenharmony_ci ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); 37662306a36Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci if (ret) 37962306a36Sopenharmony_ci return ret; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci /* Power Gates state is stored in powermisc_pwgt_state 38262306a36Sopenharmony_ci * where the meaning of bits is negated */ 38362306a36Sopenharmony_ci val = (val & ~MC13892_POWERMISC_PWGTSPI_M) | 38462306a36Sopenharmony_ci (priv->powermisc_pwgt_state ^ MC13892_POWERMISC_PWGTSPI_M); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return (val & mc13892_regulators[id].enable_bit) != 0; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic const struct regulator_ops mc13892_gpo_regulator_ops = { 39162306a36Sopenharmony_ci .enable = mc13892_gpo_regulator_enable, 39262306a36Sopenharmony_ci .disable = mc13892_gpo_regulator_disable, 39362306a36Sopenharmony_ci .is_enabled = mc13892_gpo_regulator_is_enabled, 39462306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 39562306a36Sopenharmony_ci .set_voltage = mc13xxx_fixed_regulator_set_voltage, 39662306a36Sopenharmony_ci}; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) 39962306a36Sopenharmony_ci{ 40062306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 40162306a36Sopenharmony_ci int ret, id = rdev_get_id(rdev); 40262306a36Sopenharmony_ci unsigned int val, selector; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 40762306a36Sopenharmony_ci ret = mc13xxx_reg_read(priv->mc13xxx, 40862306a36Sopenharmony_ci mc13892_regulators[id].vsel_reg, &val); 40962306a36Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 41062306a36Sopenharmony_ci if (ret) 41162306a36Sopenharmony_ci return ret; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* 41462306a36Sopenharmony_ci * Figure out if the HI bit is set inside the switcher mode register 41562306a36Sopenharmony_ci * since this means the selector value we return is at a different 41662306a36Sopenharmony_ci * offset into the selector table. 41762306a36Sopenharmony_ci * 41862306a36Sopenharmony_ci * According to the MC13892 documentation note 59 (Table 47) the SW1 41962306a36Sopenharmony_ci * buck switcher does not support output range programming therefore 42062306a36Sopenharmony_ci * the HI bit must always remain 0. So do not do anything strange if 42162306a36Sopenharmony_ci * our register is MC13892_SWITCHERS0. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci selector = val & mc13892_regulators[id].vsel_mask; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if ((mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) && 42762306a36Sopenharmony_ci (val & MC13892_SWITCHERS0_SWxHI)) { 42862306a36Sopenharmony_ci selector += MC13892_SWxHI_SEL_OFFSET; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d val: 0x%08x selector: %d\n", 43262306a36Sopenharmony_ci __func__, id, val, selector); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci return selector; 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, 43862306a36Sopenharmony_ci unsigned selector) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 44162306a36Sopenharmony_ci int volt, mask, id = rdev_get_id(rdev); 44262306a36Sopenharmony_ci u32 reg_value; 44362306a36Sopenharmony_ci int ret; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci volt = rdev->desc->volt_table[selector]; 44662306a36Sopenharmony_ci mask = mc13892_regulators[id].vsel_mask; 44762306a36Sopenharmony_ci reg_value = selector; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* 45062306a36Sopenharmony_ci * Don't mess with the HI bit or support HI voltage offsets for SW1. 45162306a36Sopenharmony_ci * 45262306a36Sopenharmony_ci * Since the get_voltage_sel callback has given a fudged value for 45362306a36Sopenharmony_ci * the selector offset, we need to back out that offset if HI is 45462306a36Sopenharmony_ci * to be set so we write the correct value to the register. 45562306a36Sopenharmony_ci * 45662306a36Sopenharmony_ci * The HI bit addition and selector offset handling COULD be more 45762306a36Sopenharmony_ci * complicated by shifting and masking off the voltage selector part 45862306a36Sopenharmony_ci * of the register then logical OR it back in, but since the selector 45962306a36Sopenharmony_ci * is at bits 4:0 there is very little point. This makes the whole 46062306a36Sopenharmony_ci * thing more readable and we do far less work. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) { 46462306a36Sopenharmony_ci mask |= MC13892_SWITCHERS0_SWxHI; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (volt > 1375000) { 46762306a36Sopenharmony_ci reg_value -= MC13892_SWxHI_SEL_OFFSET; 46862306a36Sopenharmony_ci reg_value |= MC13892_SWITCHERS0_SWxHI; 46962306a36Sopenharmony_ci } else { 47062306a36Sopenharmony_ci reg_value &= ~MC13892_SWITCHERS0_SWxHI; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 47562306a36Sopenharmony_ci ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, 47662306a36Sopenharmony_ci mask, reg_value); 47762306a36Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci return ret; 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic const struct regulator_ops mc13892_sw_regulator_ops = { 48362306a36Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 48462306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 48562306a36Sopenharmony_ci .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, 48662306a36Sopenharmony_ci .get_voltage_sel = mc13892_sw_regulator_get_voltage_sel, 48762306a36Sopenharmony_ci}; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci unsigned int en_val = 0; 49262306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 49362306a36Sopenharmony_ci int ret, id = rdev_get_id(rdev); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (mode == REGULATOR_MODE_FAST) 49662306a36Sopenharmony_ci en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 49962306a36Sopenharmony_ci ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, 50062306a36Sopenharmony_ci MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val); 50162306a36Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci return ret; 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 50962306a36Sopenharmony_ci int ret, id = rdev_get_id(rdev); 51062306a36Sopenharmony_ci unsigned int val; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 51362306a36Sopenharmony_ci ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); 51462306a36Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci if (ret) 51762306a36Sopenharmony_ci return ret; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (val & MC13892_REGULATORMODE1_VCAMCONFIGEN) 52062306a36Sopenharmony_ci return REGULATOR_MODE_FAST; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci return REGULATOR_MODE_NORMAL; 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic struct regulator_ops mc13892_vcam_ops; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic int mc13892_regulator_probe(struct platform_device *pdev) 52862306a36Sopenharmony_ci{ 52962306a36Sopenharmony_ci struct mc13xxx_regulator_priv *priv; 53062306a36Sopenharmony_ci struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); 53162306a36Sopenharmony_ci struct mc13xxx_regulator_platform_data *pdata = 53262306a36Sopenharmony_ci dev_get_platdata(&pdev->dev); 53362306a36Sopenharmony_ci struct mc13xxx_regulator_init_data *mc13xxx_data; 53462306a36Sopenharmony_ci struct regulator_config config = { }; 53562306a36Sopenharmony_ci int i, ret; 53662306a36Sopenharmony_ci int num_regulators = 0; 53762306a36Sopenharmony_ci u32 val; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci num_regulators = mc13xxx_get_num_regulators_dt(pdev); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (num_regulators <= 0 && pdata) 54262306a36Sopenharmony_ci num_regulators = pdata->num_regulators; 54362306a36Sopenharmony_ci if (num_regulators <= 0) 54462306a36Sopenharmony_ci return -EINVAL; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, 54762306a36Sopenharmony_ci struct_size(priv, regulators, num_regulators), 54862306a36Sopenharmony_ci GFP_KERNEL); 54962306a36Sopenharmony_ci if (!priv) 55062306a36Sopenharmony_ci return -ENOMEM; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci priv->num_regulators = num_regulators; 55362306a36Sopenharmony_ci priv->mc13xxx_regulators = mc13892_regulators; 55462306a36Sopenharmony_ci priv->mc13xxx = mc13892; 55562306a36Sopenharmony_ci platform_set_drvdata(pdev, priv); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci mc13xxx_lock(mc13892); 55862306a36Sopenharmony_ci ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); 55962306a36Sopenharmony_ci if (ret) 56062306a36Sopenharmony_ci goto err_unlock; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* enable switch auto mode (on 2.0A silicon only) */ 56362306a36Sopenharmony_ci if ((val & 0x0000FFFF) == 0x45d0) { 56462306a36Sopenharmony_ci ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4, 56562306a36Sopenharmony_ci MC13892_SWITCHERS4_SW1MODE_M | 56662306a36Sopenharmony_ci MC13892_SWITCHERS4_SW2MODE_M, 56762306a36Sopenharmony_ci MC13892_SWITCHERS4_SW1MODE_AUTO | 56862306a36Sopenharmony_ci MC13892_SWITCHERS4_SW2MODE_AUTO); 56962306a36Sopenharmony_ci if (ret) 57062306a36Sopenharmony_ci goto err_unlock; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5, 57362306a36Sopenharmony_ci MC13892_SWITCHERS5_SW3MODE_M | 57462306a36Sopenharmony_ci MC13892_SWITCHERS5_SW4MODE_M, 57562306a36Sopenharmony_ci MC13892_SWITCHERS5_SW3MODE_AUTO | 57662306a36Sopenharmony_ci MC13892_SWITCHERS5_SW4MODE_AUTO); 57762306a36Sopenharmony_ci if (ret) 57862306a36Sopenharmony_ci goto err_unlock; 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci mc13xxx_unlock(mc13892); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* update mc13892_vcam ops */ 58362306a36Sopenharmony_ci memcpy(&mc13892_vcam_ops, mc13892_regulators[MC13892_VCAM].desc.ops, 58462306a36Sopenharmony_ci sizeof(struct regulator_ops)); 58562306a36Sopenharmony_ci mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode; 58662306a36Sopenharmony_ci mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode; 58762306a36Sopenharmony_ci mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, 59062306a36Sopenharmony_ci ARRAY_SIZE(mc13892_regulators)); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci for (i = 0; i < priv->num_regulators; i++) { 59362306a36Sopenharmony_ci struct regulator_init_data *init_data; 59462306a36Sopenharmony_ci struct regulator_desc *desc; 59562306a36Sopenharmony_ci struct device_node *node = NULL; 59662306a36Sopenharmony_ci int id; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (mc13xxx_data) { 59962306a36Sopenharmony_ci id = mc13xxx_data[i].id; 60062306a36Sopenharmony_ci init_data = mc13xxx_data[i].init_data; 60162306a36Sopenharmony_ci node = mc13xxx_data[i].node; 60262306a36Sopenharmony_ci } else { 60362306a36Sopenharmony_ci id = pdata->regulators[i].id; 60462306a36Sopenharmony_ci init_data = pdata->regulators[i].init_data; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci desc = &mc13892_regulators[id].desc; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci config.dev = &pdev->dev; 60962306a36Sopenharmony_ci config.init_data = init_data; 61062306a36Sopenharmony_ci config.driver_data = priv; 61162306a36Sopenharmony_ci config.of_node = node; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci priv->regulators[i] = devm_regulator_register(&pdev->dev, desc, 61462306a36Sopenharmony_ci &config); 61562306a36Sopenharmony_ci if (IS_ERR(priv->regulators[i])) { 61662306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to register regulator %s\n", 61762306a36Sopenharmony_ci mc13892_regulators[i].desc.name); 61862306a36Sopenharmony_ci return PTR_ERR(priv->regulators[i]); 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return 0; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cierr_unlock: 62562306a36Sopenharmony_ci mc13xxx_unlock(mc13892); 62662306a36Sopenharmony_ci return ret; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic struct platform_driver mc13892_regulator_driver = { 63062306a36Sopenharmony_ci .driver = { 63162306a36Sopenharmony_ci .name = "mc13892-regulator", 63262306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 63362306a36Sopenharmony_ci }, 63462306a36Sopenharmony_ci .probe = mc13892_regulator_probe, 63562306a36Sopenharmony_ci}; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic int __init mc13892_regulator_init(void) 63862306a36Sopenharmony_ci{ 63962306a36Sopenharmony_ci return platform_driver_register(&mc13892_regulator_driver); 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_cisubsys_initcall(mc13892_regulator_init); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic void __exit mc13892_regulator_exit(void) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci platform_driver_unregister(&mc13892_regulator_driver); 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_cimodule_exit(mc13892_regulator_exit); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 65062306a36Sopenharmony_ciMODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); 65162306a36Sopenharmony_ciMODULE_DESCRIPTION("Regulator Driver for Freescale MC13892 PMIC"); 65262306a36Sopenharmony_ciMODULE_ALIAS("platform:mc13892-regulator"); 653