xref: /rk3399_rockchip-uboot/drivers/power/pmic/pm8916.c (revision 3bfc8152b2c09d81fb00f4d3990e5dfd59682b96)
1c2f74c8fSMateusz Kulikowski /*
2c2f74c8fSMateusz Kulikowski  * Qualcomm pm8916 pmic driver
3c2f74c8fSMateusz Kulikowski  *
4c2f74c8fSMateusz Kulikowski  * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
5c2f74c8fSMateusz Kulikowski  *
6c2f74c8fSMateusz Kulikowski  * SPDX-License-Identifier:	GPL-2.0+
7c2f74c8fSMateusz Kulikowski  */
8c2f74c8fSMateusz Kulikowski #include <common.h>
9c2f74c8fSMateusz Kulikowski #include <dm.h>
10c2f74c8fSMateusz Kulikowski #include <dm/root.h>
11c2f74c8fSMateusz Kulikowski #include <power/pmic.h>
12c2f74c8fSMateusz Kulikowski #include <spmi/spmi.h>
13c2f74c8fSMateusz Kulikowski 
14c2f74c8fSMateusz Kulikowski DECLARE_GLOBAL_DATA_PTR;
15c2f74c8fSMateusz Kulikowski 
16c2f74c8fSMateusz Kulikowski #define PID_SHIFT 8
17c2f74c8fSMateusz Kulikowski #define PID_MASK (0xFF << PID_SHIFT)
18c2f74c8fSMateusz Kulikowski #define REG_MASK 0xFF
19c2f74c8fSMateusz Kulikowski 
20c2f74c8fSMateusz Kulikowski struct pm8916_priv {
21*3bfc8152STom Rini 	uint32_t usid; /* Slave ID on SPMI bus */
22c2f74c8fSMateusz Kulikowski };
23c2f74c8fSMateusz Kulikowski 
24c2f74c8fSMateusz Kulikowski static int pm8916_reg_count(struct udevice *dev)
25c2f74c8fSMateusz Kulikowski {
26c2f74c8fSMateusz Kulikowski 	return 0xFFFF;
27c2f74c8fSMateusz Kulikowski }
28c2f74c8fSMateusz Kulikowski 
29c2f74c8fSMateusz Kulikowski static int pm8916_write(struct udevice *dev, uint reg, const uint8_t *buff,
30c2f74c8fSMateusz Kulikowski 			int len)
31c2f74c8fSMateusz Kulikowski {
32c2f74c8fSMateusz Kulikowski 	struct pm8916_priv *priv = dev_get_priv(dev);
33c2f74c8fSMateusz Kulikowski 
34c2f74c8fSMateusz Kulikowski 	if (len != 1)
35c2f74c8fSMateusz Kulikowski 		return -EINVAL;
36c2f74c8fSMateusz Kulikowski 
37c2f74c8fSMateusz Kulikowski 	return spmi_reg_write(dev->parent, priv->usid,
38c2f74c8fSMateusz Kulikowski 			      (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK,
39c2f74c8fSMateusz Kulikowski 			      *buff);
40c2f74c8fSMateusz Kulikowski }
41c2f74c8fSMateusz Kulikowski 
42c2f74c8fSMateusz Kulikowski static int pm8916_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
43c2f74c8fSMateusz Kulikowski {
44c2f74c8fSMateusz Kulikowski 	struct pm8916_priv *priv = dev_get_priv(dev);
45c2f74c8fSMateusz Kulikowski 	int val;
46c2f74c8fSMateusz Kulikowski 
47c2f74c8fSMateusz Kulikowski 	if (len != 1)
48c2f74c8fSMateusz Kulikowski 		return -EINVAL;
49c2f74c8fSMateusz Kulikowski 
50c2f74c8fSMateusz Kulikowski 	val = spmi_reg_read(dev->parent, priv->usid,
51c2f74c8fSMateusz Kulikowski 			    (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK);
52c2f74c8fSMateusz Kulikowski 
53c2f74c8fSMateusz Kulikowski 	if (val < 0)
54c2f74c8fSMateusz Kulikowski 		return val;
55c2f74c8fSMateusz Kulikowski 	*buff = val;
56c2f74c8fSMateusz Kulikowski 	return 0;
57c2f74c8fSMateusz Kulikowski }
58c2f74c8fSMateusz Kulikowski 
59c2f74c8fSMateusz Kulikowski static struct dm_pmic_ops pm8916_ops = {
60c2f74c8fSMateusz Kulikowski 	.reg_count = pm8916_reg_count,
61c2f74c8fSMateusz Kulikowski 	.read = pm8916_read,
62c2f74c8fSMateusz Kulikowski 	.write = pm8916_write,
63c2f74c8fSMateusz Kulikowski };
64c2f74c8fSMateusz Kulikowski 
65c2f74c8fSMateusz Kulikowski static const struct udevice_id pm8916_ids[] = {
66c2f74c8fSMateusz Kulikowski 	{ .compatible = "qcom,spmi-pmic" },
67c2f74c8fSMateusz Kulikowski 	{ }
68c2f74c8fSMateusz Kulikowski };
69c2f74c8fSMateusz Kulikowski 
70c2f74c8fSMateusz Kulikowski static int pm8916_probe(struct udevice *dev)
71c2f74c8fSMateusz Kulikowski {
72c2f74c8fSMateusz Kulikowski 	struct pm8916_priv *priv = dev_get_priv(dev);
73c2f74c8fSMateusz Kulikowski 
74c2f74c8fSMateusz Kulikowski 	priv->usid = dev_get_addr(dev);
75c2f74c8fSMateusz Kulikowski 
76c2f74c8fSMateusz Kulikowski 	if (priv->usid == FDT_ADDR_T_NONE)
77c2f74c8fSMateusz Kulikowski 		return -EINVAL;
78c2f74c8fSMateusz Kulikowski 
79c2f74c8fSMateusz Kulikowski 	return 0;
80c2f74c8fSMateusz Kulikowski }
81c2f74c8fSMateusz Kulikowski 
82c2f74c8fSMateusz Kulikowski 
83c2f74c8fSMateusz Kulikowski static int pm8916_bind(struct udevice *dev)
84c2f74c8fSMateusz Kulikowski {
85c2f74c8fSMateusz Kulikowski 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
86c2f74c8fSMateusz Kulikowski }
87c2f74c8fSMateusz Kulikowski 
88c2f74c8fSMateusz Kulikowski U_BOOT_DRIVER(pmic_pm8916) = {
89c2f74c8fSMateusz Kulikowski 	.name = "pmic_pm8916",
90c2f74c8fSMateusz Kulikowski 	.id = UCLASS_PMIC,
91c2f74c8fSMateusz Kulikowski 	.of_match = pm8916_ids,
92c2f74c8fSMateusz Kulikowski 	.bind = pm8916_bind,
93c2f74c8fSMateusz Kulikowski 	.probe = pm8916_probe,
94c2f74c8fSMateusz Kulikowski 	.ops = &pm8916_ops,
95c2f74c8fSMateusz Kulikowski 	.priv_auto_alloc_size = sizeof(struct pm8916_priv),
96c2f74c8fSMateusz Kulikowski };
97