1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Qualcomm generic pmic driver 4 * 5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> 6 */ 7#include <common.h> 8#include <dm.h> 9#include <power/pmic.h> 10#include <spmi/spmi.h> 11 12#define PID_SHIFT 8 13#define PID_MASK (0xFF << PID_SHIFT) 14#define REG_MASK 0xFF 15 16struct pmic_qcom_priv { 17 uint32_t usid; /* Slave ID on SPMI bus */ 18}; 19 20static int pmic_qcom_reg_count(struct udevice *dev) 21{ 22 return 0xFFFF; 23} 24 25static int pmic_qcom_write(struct udevice *dev, uint reg, const uint8_t *buff, 26 int len) 27{ 28 struct pmic_qcom_priv *priv = dev_get_priv(dev); 29 30 if (len != 1) 31 return -EINVAL; 32 33 return spmi_reg_write(dev->parent, priv->usid, 34 (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK, 35 *buff); 36} 37 38static int pmic_qcom_read(struct udevice *dev, uint reg, uint8_t *buff, int len) 39{ 40 struct pmic_qcom_priv *priv = dev_get_priv(dev); 41 int val; 42 43 if (len != 1) 44 return -EINVAL; 45 46 val = spmi_reg_read(dev->parent, priv->usid, 47 (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK); 48 49 if (val < 0) 50 return val; 51 *buff = val; 52 return 0; 53} 54 55static struct dm_pmic_ops pmic_qcom_ops = { 56 .reg_count = pmic_qcom_reg_count, 57 .read = pmic_qcom_read, 58 .write = pmic_qcom_write, 59}; 60 61static const struct udevice_id pmic_qcom_ids[] = { 62 { .compatible = "qcom,spmi-pmic" }, 63 { } 64}; 65 66static int pmic_qcom_probe(struct udevice *dev) 67{ 68 struct pmic_qcom_priv *priv = dev_get_priv(dev); 69 int ret; 70 71 /* 72 * dev_read_addr() can't be used here because the reg property actually 73 * contains two discrete values, not a single 64-bit address. 74 * The address is the first value. 75 */ 76 ret = ofnode_read_u32_index(dev_ofnode(dev), "reg", 0, &priv->usid); 77 if (ret < 0) 78 return -EINVAL; 79 80 debug("usid: %d\n", priv->usid); 81 82 return 0; 83} 84 85U_BOOT_DRIVER(pmic_qcom) = { 86 .name = "pmic_qcom", 87 .id = UCLASS_PMIC, 88 .of_match = pmic_qcom_ids, 89 .bind = dm_scan_fdt_dev, 90 .probe = pmic_qcom_probe, 91 .ops = &pmic_qcom_ops, 92 .priv_auto = sizeof(struct pmic_qcom_priv), 93}; 94