18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Regulator Driver for Freescale MC13892 PMIC 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright 2010 Yong Shen <yong.shen@linaro.org> 68c2ecf20Sopenharmony_ci// 78c2ecf20Sopenharmony_ci// Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/mfd/mc13892.h> 108c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 118c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include "mc13xxx.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define MC13892_REVISION 7 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define MC13892_POWERCTL0 13 238c2ecf20Sopenharmony_ci#define MC13892_POWERCTL0_USEROFFSPI 3 248c2ecf20Sopenharmony_ci#define MC13892_POWERCTL0_VCOINCELLVSEL 20 258c2ecf20Sopenharmony_ci#define MC13892_POWERCTL0_VCOINCELLVSEL_M (7<<20) 268c2ecf20Sopenharmony_ci#define MC13892_POWERCTL0_VCOINCELLEN (1<<23) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS0_SWxHI (1<<23) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS0 24 318c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS0_SW1VSEL 0 328c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS0_SW1VSEL_M (0x1f<<0) 338c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS0_SW1HI (1<<23) 348c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS0_SW1EN 0 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS1 25 378c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS1_SW2VSEL 0 388c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS1_SW2VSEL_M (0x1f<<0) 398c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS1_SW2HI (1<<23) 408c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS1_SW2EN 0 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS2 26 438c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS2_SW3VSEL 0 448c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS2_SW3VSEL_M (0x1f<<0) 458c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS2_SW3HI (1<<23) 468c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS2_SW3EN 0 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS3 27 498c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS3_SW4VSEL 0 508c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS3_SW4VSEL_M (0x1f<<0) 518c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS3_SW4HI (1<<23) 528c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS3_SW4EN 0 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4 28 558c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4_SW1MODE 0 568c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4_SW1MODE_AUTO (8<<0) 578c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4_SW1MODE_M (0xf<<0) 588c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4_SW2MODE 10 598c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4_SW2MODE_AUTO (8<<10) 608c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS4_SW2MODE_M (0xf<<10) 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5 29 638c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SW3MODE 0 648c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SW3MODE_AUTO (8<<0) 658c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SW3MODE_M (0xf<<0) 668c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SW4MODE 8 678c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SW4MODE_AUTO (8<<8) 688c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SW4MODE_M (0xf<<8) 698c2ecf20Sopenharmony_ci#define MC13892_SWITCHERS5_SWBSTEN (1<<20) 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0 30 728c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN1VSEL 0 738c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VDIGVSEL 4 748c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN2VSEL 6 758c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VPLLVSEL 9 768c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VUSB2VSEL 11 778c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN3VSEL 14 788c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VCAMVSEL 16 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN1VSEL_M (3<<0) 818c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VDIGVSEL_M (3<<4) 828c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN2VSEL_M (7<<6) 838c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VPLLVSEL_M (3<<9) 848c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VUSB2VSEL_M (3<<11) 858c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VGEN3VSEL_M (1<<14) 868c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING0_VCAMVSEL_M (3<<16) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1 31 898c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1_VVIDEOVSEL 2 908c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1_VAUDIOVSEL 4 918c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1_VSDVSEL 6 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1_VVIDEOVSEL_M (3<<2) 948c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1_VAUDIOVSEL_M (3<<4) 958c2ecf20Sopenharmony_ci#define MC13892_REGULATORSETTING1_VSDVSEL_M (7<<6) 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0 32 988c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN1EN (1<<0) 998c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN1STDBY (1<<1) 1008c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN1MODE (1<<2) 1018c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VIOHIEN (1<<3) 1028c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VIOHISTDBY (1<<4) 1038c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VIOHIMODE (1<<5) 1048c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VDIGEN (1<<9) 1058c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VDIGSTDBY (1<<10) 1068c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VDIGMODE (1<<11) 1078c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN2EN (1<<12) 1088c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN2STDBY (1<<13) 1098c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VGEN2MODE (1<<14) 1108c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VPLLEN (1<<15) 1118c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VPLLSTDBY (1<<16) 1128c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VPLLMODE (1<<17) 1138c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VUSB2EN (1<<18) 1148c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VUSB2STDBY (1<<19) 1158c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE0_VUSB2MODE (1<<20) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1 33 1188c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VGEN3EN (1<<0) 1198c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VGEN3STDBY (1<<1) 1208c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VGEN3MODE (1<<2) 1218c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMEN (1<<6) 1228c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMSTDBY (1<<7) 1238c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMMODE (1<<8) 1248c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VCAMCONFIGEN (1<<9) 1258c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VVIDEOEN (1<<12) 1268c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VVIDEOSTDBY (1<<13) 1278c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VVIDEOMODE (1<<14) 1288c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VAUDIOEN (1<<15) 1298c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VAUDIOSTDBY (1<<16) 1308c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VAUDIOMODE (1<<17) 1318c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VSDEN (1<<18) 1328c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VSDSTDBY (1<<19) 1338c2ecf20Sopenharmony_ci#define MC13892_REGULATORMODE1_VSDMODE (1<<20) 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci#define MC13892_POWERMISC 34 1368c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_GPO1EN (1<<6) 1378c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_GPO2EN (1<<8) 1388c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_GPO3EN (1<<10) 1398c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_GPO4EN (1<<12) 1408c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_PWGT1SPIEN (1<<15) 1418c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_PWGT2SPIEN (1<<16) 1428c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_GPO4ADINEN (1<<21) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define MC13892_POWERMISC_PWGTSPI_M (3 << 15) 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci#define MC13892_USB1 50 1478c2ecf20Sopenharmony_ci#define MC13892_USB1_VUSBEN (1<<3) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vcoincell[] = { 1508c2ecf20Sopenharmony_ci 2500000, 2700000, 2800000, 2900000, 3000000, 3100000, 1518c2ecf20Sopenharmony_ci 3200000, 3300000, 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic const unsigned int mc13892_sw1[] = { 1558c2ecf20Sopenharmony_ci 600000, 625000, 650000, 675000, 700000, 725000, 1568c2ecf20Sopenharmony_ci 750000, 775000, 800000, 825000, 850000, 875000, 1578c2ecf20Sopenharmony_ci 900000, 925000, 950000, 975000, 1000000, 1025000, 1588c2ecf20Sopenharmony_ci 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1598c2ecf20Sopenharmony_ci 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1608c2ecf20Sopenharmony_ci 1350000, 1375000 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* 1648c2ecf20Sopenharmony_ci * Note: this table is used to derive SWxVSEL by index into 1658c2ecf20Sopenharmony_ci * the array. Offset the values by the index of 1100000uV 1668c2ecf20Sopenharmony_ci * to get the actual register value for that voltage selector 1678c2ecf20Sopenharmony_ci * if the HI bit is to be set as well. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci#define MC13892_SWxHI_SEL_OFFSET 20 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic const unsigned int mc13892_sw[] = { 1728c2ecf20Sopenharmony_ci 600000, 625000, 650000, 675000, 700000, 725000, 1738c2ecf20Sopenharmony_ci 750000, 775000, 800000, 825000, 850000, 875000, 1748c2ecf20Sopenharmony_ci 900000, 925000, 950000, 975000, 1000000, 1025000, 1758c2ecf20Sopenharmony_ci 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1768c2ecf20Sopenharmony_ci 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1778c2ecf20Sopenharmony_ci 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1788c2ecf20Sopenharmony_ci 1500000, 1525000, 1550000, 1575000, 1600000, 1625000, 1798c2ecf20Sopenharmony_ci 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1808c2ecf20Sopenharmony_ci 1800000, 1825000, 1850000, 1875000 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic const unsigned int mc13892_swbst[] = { 1848c2ecf20Sopenharmony_ci 5000000, 1858c2ecf20Sopenharmony_ci}; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic const unsigned int mc13892_viohi[] = { 1888c2ecf20Sopenharmony_ci 2775000, 1898c2ecf20Sopenharmony_ci}; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vpll[] = { 1928c2ecf20Sopenharmony_ci 1050000, 1250000, 1650000, 1800000, 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vdig[] = { 1968c2ecf20Sopenharmony_ci 1050000, 1250000, 1650000, 1800000, 1978c2ecf20Sopenharmony_ci}; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vsd[] = { 2008c2ecf20Sopenharmony_ci 1800000, 2000000, 2600000, 2700000, 2018c2ecf20Sopenharmony_ci 2800000, 2900000, 3000000, 3150000, 2028c2ecf20Sopenharmony_ci}; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vusb2[] = { 2058c2ecf20Sopenharmony_ci 2400000, 2600000, 2700000, 2775000, 2068c2ecf20Sopenharmony_ci}; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vvideo[] = { 2098c2ecf20Sopenharmony_ci 2700000, 2775000, 2500000, 2600000, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vaudio[] = { 2138c2ecf20Sopenharmony_ci 2300000, 2500000, 2775000, 3000000, 2148c2ecf20Sopenharmony_ci}; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vcam[] = { 2178c2ecf20Sopenharmony_ci 2500000, 2600000, 2750000, 3000000, 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vgen1[] = { 2218c2ecf20Sopenharmony_ci 1200000, 1500000, 2775000, 3150000, 2228c2ecf20Sopenharmony_ci}; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vgen2[] = { 2258c2ecf20Sopenharmony_ci 1200000, 1500000, 1600000, 1800000, 2268c2ecf20Sopenharmony_ci 2700000, 2800000, 3000000, 3150000, 2278c2ecf20Sopenharmony_ci}; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vgen3[] = { 2308c2ecf20Sopenharmony_ci 1800000, 2900000, 2318c2ecf20Sopenharmony_ci}; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic const unsigned int mc13892_vusb[] = { 2348c2ecf20Sopenharmony_ci 3300000, 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic const unsigned int mc13892_gpo[] = { 2388c2ecf20Sopenharmony_ci 2750000, 2398c2ecf20Sopenharmony_ci}; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const unsigned int mc13892_pwgtdrv[] = { 2428c2ecf20Sopenharmony_ci 5000000, 2438c2ecf20Sopenharmony_ci}; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic const struct regulator_ops mc13892_gpo_regulator_ops; 2468c2ecf20Sopenharmony_cistatic const struct regulator_ops mc13892_sw_regulator_ops; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci#define MC13892_FIXED_DEFINE(name, node, reg, voltages) \ 2508c2ecf20Sopenharmony_ci MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages, \ 2518c2ecf20Sopenharmony_ci mc13xxx_fixed_regulator_ops) 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci#define MC13892_GPO_DEFINE(name, node, reg, voltages) \ 2548c2ecf20Sopenharmony_ci MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages, \ 2558c2ecf20Sopenharmony_ci mc13892_gpo_regulator_ops) 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci#define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages) \ 2588c2ecf20Sopenharmony_ci MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ 2598c2ecf20Sopenharmony_ci mc13892_sw_regulator_ops) 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci#define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages) \ 2628c2ecf20Sopenharmony_ci MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \ 2638c2ecf20Sopenharmony_ci mc13xxx_regulator_ops) 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic struct mc13xxx_regulator mc13892_regulators[] = { 2668c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell), 2678c2ecf20Sopenharmony_ci MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1), 2688c2ecf20Sopenharmony_ci MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw), 2698c2ecf20Sopenharmony_ci MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw), 2708c2ecf20Sopenharmony_ci MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw), 2718c2ecf20Sopenharmony_ci MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst), 2728c2ecf20Sopenharmony_ci MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi), 2738c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0, 2748c2ecf20Sopenharmony_ci mc13892_vpll), 2758c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0, 2768c2ecf20Sopenharmony_ci mc13892_vdig), 2778c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1, 2788c2ecf20Sopenharmony_ci mc13892_vsd), 2798c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0, 2808c2ecf20Sopenharmony_ci mc13892_vusb2), 2818c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1, 2828c2ecf20Sopenharmony_ci mc13892_vvideo), 2838c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1, 2848c2ecf20Sopenharmony_ci mc13892_vaudio), 2858c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0, 2868c2ecf20Sopenharmony_ci mc13892_vcam), 2878c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0, 2888c2ecf20Sopenharmony_ci mc13892_vgen1), 2898c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0, 2908c2ecf20Sopenharmony_ci mc13892_vgen2), 2918c2ecf20Sopenharmony_ci MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0, 2928c2ecf20Sopenharmony_ci mc13892_vgen3), 2938c2ecf20Sopenharmony_ci MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb), 2948c2ecf20Sopenharmony_ci MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo), 2958c2ecf20Sopenharmony_ci MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo), 2968c2ecf20Sopenharmony_ci MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo), 2978c2ecf20Sopenharmony_ci MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo), 2988c2ecf20Sopenharmony_ci MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv), 2998c2ecf20Sopenharmony_ci MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv), 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, 3038c2ecf20Sopenharmony_ci u32 val) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct mc13xxx *mc13892 = priv->mc13xxx; 3068c2ecf20Sopenharmony_ci int ret; 3078c2ecf20Sopenharmony_ci u32 valread; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci BUG_ON(val & ~mask); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 3128c2ecf20Sopenharmony_ci ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread); 3138c2ecf20Sopenharmony_ci if (ret) 3148c2ecf20Sopenharmony_ci goto out; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* Update the stored state for Power Gates. */ 3178c2ecf20Sopenharmony_ci priv->powermisc_pwgt_state = 3188c2ecf20Sopenharmony_ci (priv->powermisc_pwgt_state & ~mask) | val; 3198c2ecf20Sopenharmony_ci priv->powermisc_pwgt_state &= MC13892_POWERMISC_PWGTSPI_M; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Construct the new register value */ 3228c2ecf20Sopenharmony_ci valread = (valread & ~mask) | val; 3238c2ecf20Sopenharmony_ci /* Overwrite the PWGTxEN with the stored version */ 3248c2ecf20Sopenharmony_ci valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) | 3258c2ecf20Sopenharmony_ci priv->powermisc_pwgt_state; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci ret = mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); 3288c2ecf20Sopenharmony_ciout: 3298c2ecf20Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 3308c2ecf20Sopenharmony_ci return ret; 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 3368c2ecf20Sopenharmony_ci int id = rdev_get_id(rdev); 3378c2ecf20Sopenharmony_ci u32 en_val = mc13892_regulators[id].enable_bit; 3388c2ecf20Sopenharmony_ci u32 mask = mc13892_regulators[id].enable_bit; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* Power Gate enable value is 0 */ 3438c2ecf20Sopenharmony_ci if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) 3448c2ecf20Sopenharmony_ci en_val = 0; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (id == MC13892_GPO4) 3478c2ecf20Sopenharmony_ci mask |= MC13892_POWERMISC_GPO4ADINEN; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci return mc13892_powermisc_rmw(priv, mask, en_val); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 3558c2ecf20Sopenharmony_ci int id = rdev_get_id(rdev); 3568c2ecf20Sopenharmony_ci u32 dis_val = 0; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci /* Power Gate disable value is 1 */ 3618c2ecf20Sopenharmony_ci if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) 3628c2ecf20Sopenharmony_ci dis_val = mc13892_regulators[id].enable_bit; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, 3658c2ecf20Sopenharmony_ci dis_val); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 3718c2ecf20Sopenharmony_ci int ret, id = rdev_get_id(rdev); 3728c2ecf20Sopenharmony_ci unsigned int val; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 3758c2ecf20Sopenharmony_ci ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); 3768c2ecf20Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (ret) 3798c2ecf20Sopenharmony_ci return ret; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* Power Gates state is stored in powermisc_pwgt_state 3828c2ecf20Sopenharmony_ci * where the meaning of bits is negated */ 3838c2ecf20Sopenharmony_ci val = (val & ~MC13892_POWERMISC_PWGTSPI_M) | 3848c2ecf20Sopenharmony_ci (priv->powermisc_pwgt_state ^ MC13892_POWERMISC_PWGTSPI_M); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci return (val & mc13892_regulators[id].enable_bit) != 0; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic const struct regulator_ops mc13892_gpo_regulator_ops = { 3918c2ecf20Sopenharmony_ci .enable = mc13892_gpo_regulator_enable, 3928c2ecf20Sopenharmony_ci .disable = mc13892_gpo_regulator_disable, 3938c2ecf20Sopenharmony_ci .is_enabled = mc13892_gpo_regulator_is_enabled, 3948c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 3958c2ecf20Sopenharmony_ci .set_voltage = mc13xxx_fixed_regulator_set_voltage, 3968c2ecf20Sopenharmony_ci}; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 4018c2ecf20Sopenharmony_ci int ret, id = rdev_get_id(rdev); 4028c2ecf20Sopenharmony_ci unsigned int val, selector; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 4078c2ecf20Sopenharmony_ci ret = mc13xxx_reg_read(priv->mc13xxx, 4088c2ecf20Sopenharmony_ci mc13892_regulators[id].vsel_reg, &val); 4098c2ecf20Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 4108c2ecf20Sopenharmony_ci if (ret) 4118c2ecf20Sopenharmony_ci return ret; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* 4148c2ecf20Sopenharmony_ci * Figure out if the HI bit is set inside the switcher mode register 4158c2ecf20Sopenharmony_ci * since this means the selector value we return is at a different 4168c2ecf20Sopenharmony_ci * offset into the selector table. 4178c2ecf20Sopenharmony_ci * 4188c2ecf20Sopenharmony_ci * According to the MC13892 documentation note 59 (Table 47) the SW1 4198c2ecf20Sopenharmony_ci * buck switcher does not support output range programming therefore 4208c2ecf20Sopenharmony_ci * the HI bit must always remain 0. So do not do anything strange if 4218c2ecf20Sopenharmony_ci * our register is MC13892_SWITCHERS0. 4228c2ecf20Sopenharmony_ci */ 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci selector = val & mc13892_regulators[id].vsel_mask; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if ((mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) && 4278c2ecf20Sopenharmony_ci (val & MC13892_SWITCHERS0_SWxHI)) { 4288c2ecf20Sopenharmony_ci selector += MC13892_SWxHI_SEL_OFFSET; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci dev_dbg(rdev_get_dev(rdev), "%s id: %d val: 0x%08x selector: %d\n", 4328c2ecf20Sopenharmony_ci __func__, id, val, selector); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci return selector; 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, 4388c2ecf20Sopenharmony_ci unsigned selector) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 4418c2ecf20Sopenharmony_ci int volt, mask, id = rdev_get_id(rdev); 4428c2ecf20Sopenharmony_ci u32 reg_value; 4438c2ecf20Sopenharmony_ci int ret; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci volt = rdev->desc->volt_table[selector]; 4468c2ecf20Sopenharmony_ci mask = mc13892_regulators[id].vsel_mask; 4478c2ecf20Sopenharmony_ci reg_value = selector; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci /* 4508c2ecf20Sopenharmony_ci * Don't mess with the HI bit or support HI voltage offsets for SW1. 4518c2ecf20Sopenharmony_ci * 4528c2ecf20Sopenharmony_ci * Since the get_voltage_sel callback has given a fudged value for 4538c2ecf20Sopenharmony_ci * the selector offset, we need to back out that offset if HI is 4548c2ecf20Sopenharmony_ci * to be set so we write the correct value to the register. 4558c2ecf20Sopenharmony_ci * 4568c2ecf20Sopenharmony_ci * The HI bit addition and selector offset handling COULD be more 4578c2ecf20Sopenharmony_ci * complicated by shifting and masking off the voltage selector part 4588c2ecf20Sopenharmony_ci * of the register then logical OR it back in, but since the selector 4598c2ecf20Sopenharmony_ci * is at bits 4:0 there is very little point. This makes the whole 4608c2ecf20Sopenharmony_ci * thing more readable and we do far less work. 4618c2ecf20Sopenharmony_ci */ 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) { 4648c2ecf20Sopenharmony_ci mask |= MC13892_SWITCHERS0_SWxHI; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if (volt > 1375000) { 4678c2ecf20Sopenharmony_ci reg_value -= MC13892_SWxHI_SEL_OFFSET; 4688c2ecf20Sopenharmony_ci reg_value |= MC13892_SWITCHERS0_SWxHI; 4698c2ecf20Sopenharmony_ci } else { 4708c2ecf20Sopenharmony_ci reg_value &= ~MC13892_SWITCHERS0_SWxHI; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 4758c2ecf20Sopenharmony_ci ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, 4768c2ecf20Sopenharmony_ci mask, reg_value); 4778c2ecf20Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci return ret; 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic const struct regulator_ops mc13892_sw_regulator_ops = { 4838c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_table, 4848c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_ascend, 4858c2ecf20Sopenharmony_ci .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel, 4868c2ecf20Sopenharmony_ci .get_voltage_sel = mc13892_sw_regulator_get_voltage_sel, 4878c2ecf20Sopenharmony_ci}; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode) 4908c2ecf20Sopenharmony_ci{ 4918c2ecf20Sopenharmony_ci unsigned int en_val = 0; 4928c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 4938c2ecf20Sopenharmony_ci int ret, id = rdev_get_id(rdev); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (mode == REGULATOR_MODE_FAST) 4968c2ecf20Sopenharmony_ci en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 4998c2ecf20Sopenharmony_ci ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, 5008c2ecf20Sopenharmony_ci MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val); 5018c2ecf20Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci return ret; 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); 5098c2ecf20Sopenharmony_ci int ret, id = rdev_get_id(rdev); 5108c2ecf20Sopenharmony_ci unsigned int val; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci mc13xxx_lock(priv->mc13xxx); 5138c2ecf20Sopenharmony_ci ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); 5148c2ecf20Sopenharmony_ci mc13xxx_unlock(priv->mc13xxx); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci if (ret) 5178c2ecf20Sopenharmony_ci return ret; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (val & MC13892_REGULATORMODE1_VCAMCONFIGEN) 5208c2ecf20Sopenharmony_ci return REGULATOR_MODE_FAST; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci return REGULATOR_MODE_NORMAL; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic struct regulator_ops mc13892_vcam_ops; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_cistatic int mc13892_regulator_probe(struct platform_device *pdev) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci struct mc13xxx_regulator_priv *priv; 5308c2ecf20Sopenharmony_ci struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); 5318c2ecf20Sopenharmony_ci struct mc13xxx_regulator_platform_data *pdata = 5328c2ecf20Sopenharmony_ci dev_get_platdata(&pdev->dev); 5338c2ecf20Sopenharmony_ci struct mc13xxx_regulator_init_data *mc13xxx_data; 5348c2ecf20Sopenharmony_ci struct regulator_config config = { }; 5358c2ecf20Sopenharmony_ci int i, ret; 5368c2ecf20Sopenharmony_ci int num_regulators = 0; 5378c2ecf20Sopenharmony_ci u32 val; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci num_regulators = mc13xxx_get_num_regulators_dt(pdev); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if (num_regulators <= 0 && pdata) 5428c2ecf20Sopenharmony_ci num_regulators = pdata->num_regulators; 5438c2ecf20Sopenharmony_ci if (num_regulators <= 0) 5448c2ecf20Sopenharmony_ci return -EINVAL; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, 5478c2ecf20Sopenharmony_ci struct_size(priv, regulators, num_regulators), 5488c2ecf20Sopenharmony_ci GFP_KERNEL); 5498c2ecf20Sopenharmony_ci if (!priv) 5508c2ecf20Sopenharmony_ci return -ENOMEM; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci priv->num_regulators = num_regulators; 5538c2ecf20Sopenharmony_ci priv->mc13xxx_regulators = mc13892_regulators; 5548c2ecf20Sopenharmony_ci priv->mc13xxx = mc13892; 5558c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, priv); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci mc13xxx_lock(mc13892); 5588c2ecf20Sopenharmony_ci ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); 5598c2ecf20Sopenharmony_ci if (ret) 5608c2ecf20Sopenharmony_ci goto err_unlock; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci /* enable switch auto mode (on 2.0A silicon only) */ 5638c2ecf20Sopenharmony_ci if ((val & 0x0000FFFF) == 0x45d0) { 5648c2ecf20Sopenharmony_ci ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4, 5658c2ecf20Sopenharmony_ci MC13892_SWITCHERS4_SW1MODE_M | 5668c2ecf20Sopenharmony_ci MC13892_SWITCHERS4_SW2MODE_M, 5678c2ecf20Sopenharmony_ci MC13892_SWITCHERS4_SW1MODE_AUTO | 5688c2ecf20Sopenharmony_ci MC13892_SWITCHERS4_SW2MODE_AUTO); 5698c2ecf20Sopenharmony_ci if (ret) 5708c2ecf20Sopenharmony_ci goto err_unlock; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5, 5738c2ecf20Sopenharmony_ci MC13892_SWITCHERS5_SW3MODE_M | 5748c2ecf20Sopenharmony_ci MC13892_SWITCHERS5_SW4MODE_M, 5758c2ecf20Sopenharmony_ci MC13892_SWITCHERS5_SW3MODE_AUTO | 5768c2ecf20Sopenharmony_ci MC13892_SWITCHERS5_SW4MODE_AUTO); 5778c2ecf20Sopenharmony_ci if (ret) 5788c2ecf20Sopenharmony_ci goto err_unlock; 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci mc13xxx_unlock(mc13892); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci /* update mc13892_vcam ops */ 5838c2ecf20Sopenharmony_ci memcpy(&mc13892_vcam_ops, mc13892_regulators[MC13892_VCAM].desc.ops, 5848c2ecf20Sopenharmony_ci sizeof(struct regulator_ops)); 5858c2ecf20Sopenharmony_ci mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode, 5868c2ecf20Sopenharmony_ci mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode, 5878c2ecf20Sopenharmony_ci mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, 5908c2ecf20Sopenharmony_ci ARRAY_SIZE(mc13892_regulators)); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci for (i = 0; i < priv->num_regulators; i++) { 5938c2ecf20Sopenharmony_ci struct regulator_init_data *init_data; 5948c2ecf20Sopenharmony_ci struct regulator_desc *desc; 5958c2ecf20Sopenharmony_ci struct device_node *node = NULL; 5968c2ecf20Sopenharmony_ci int id; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (mc13xxx_data) { 5998c2ecf20Sopenharmony_ci id = mc13xxx_data[i].id; 6008c2ecf20Sopenharmony_ci init_data = mc13xxx_data[i].init_data; 6018c2ecf20Sopenharmony_ci node = mc13xxx_data[i].node; 6028c2ecf20Sopenharmony_ci } else { 6038c2ecf20Sopenharmony_ci id = pdata->regulators[i].id; 6048c2ecf20Sopenharmony_ci init_data = pdata->regulators[i].init_data; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci desc = &mc13892_regulators[id].desc; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci config.dev = &pdev->dev; 6098c2ecf20Sopenharmony_ci config.init_data = init_data; 6108c2ecf20Sopenharmony_ci config.driver_data = priv; 6118c2ecf20Sopenharmony_ci config.of_node = node; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci priv->regulators[i] = devm_regulator_register(&pdev->dev, desc, 6148c2ecf20Sopenharmony_ci &config); 6158c2ecf20Sopenharmony_ci if (IS_ERR(priv->regulators[i])) { 6168c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to register regulator %s\n", 6178c2ecf20Sopenharmony_ci mc13892_regulators[i].desc.name); 6188c2ecf20Sopenharmony_ci return PTR_ERR(priv->regulators[i]); 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci return 0; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_cierr_unlock: 6258c2ecf20Sopenharmony_ci mc13xxx_unlock(mc13892); 6268c2ecf20Sopenharmony_ci return ret; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic struct platform_driver mc13892_regulator_driver = { 6308c2ecf20Sopenharmony_ci .driver = { 6318c2ecf20Sopenharmony_ci .name = "mc13892-regulator", 6328c2ecf20Sopenharmony_ci }, 6338c2ecf20Sopenharmony_ci .probe = mc13892_regulator_probe, 6348c2ecf20Sopenharmony_ci}; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic int __init mc13892_regulator_init(void) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci return platform_driver_register(&mc13892_regulator_driver); 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_cisubsys_initcall(mc13892_regulator_init); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_cistatic void __exit mc13892_regulator_exit(void) 6438c2ecf20Sopenharmony_ci{ 6448c2ecf20Sopenharmony_ci platform_driver_unregister(&mc13892_regulator_driver); 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_cimodule_exit(mc13892_regulator_exit); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 6498c2ecf20Sopenharmony_ciMODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); 6508c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Regulator Driver for Freescale MC13892 PMIC"); 6518c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:mc13892-regulator"); 652