xref: /openbmc/u-boot/drivers/spmi/spmi-msm.c (revision 77c42611)
1 /*
2  * Qualcomm SPMI bus driver
3  *
4  * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
5  *
6  * Loosely based on Little Kernel driver
7  *
8  * SPDX-License-Identifier:	BSD-3-Clause
9  */
10 
11 #include <common.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <fdtdec.h>
15 #include <asm/io.h>
16 #include <spmi/spmi.h>
17 
18 DECLARE_GLOBAL_DATA_PTR;
19 
20 /* PMIC Arbiter configuration registers */
21 #define PMIC_ARB_VERSION		0x0000
22 #define PMIC_ARB_VERSION_V2_MIN		0x20010000
23 
24 #define ARB_CHANNEL_OFFSET(n)		(0x4 * (n))
25 #define SPMI_CH_OFFSET(chnl)		((chnl) * 0x8000)
26 
27 #define SPMI_REG_CMD0			0x0
28 #define SPMI_REG_CONFIG			0x4
29 #define SPMI_REG_STATUS			0x8
30 #define SPMI_REG_WDATA			0x10
31 #define SPMI_REG_RDATA			0x18
32 
33 #define SPMI_CMD_OPCODE_SHIFT		27
34 #define SPMI_CMD_SLAVE_ID_SHIFT		20
35 #define SPMI_CMD_ADDR_SHIFT		12
36 #define SPMI_CMD_ADDR_OFFSET_SHIFT	4
37 #define SPMI_CMD_BYTE_CNT_SHIFT		0
38 
39 #define SPMI_CMD_EXT_REG_WRITE_LONG	0x00
40 #define SPMI_CMD_EXT_REG_READ_LONG	0x01
41 
42 #define SPMI_STATUS_DONE		0x1
43 
44 #define SPMI_MAX_CHANNELS	128
45 #define SPMI_MAX_SLAVES		16
46 #define SPMI_MAX_PERIPH		256
47 
48 struct msm_spmi_priv {
49 	phys_addr_t arb_chnl; /* ARB channel mapping base */
50 	phys_addr_t spmi_core; /* SPMI core */
51 	phys_addr_t spmi_obs; /* SPMI observer */
52 	/* SPMI channel map */
53 	uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH];
54 };
55 
56 static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
57 			  uint8_t val)
58 {
59 	struct msm_spmi_priv *priv = dev_get_priv(dev);
60 	unsigned channel;
61 	uint32_t reg = 0;
62 
63 	if (usid >= SPMI_MAX_SLAVES)
64 		return -EIO;
65 	if (pid >= SPMI_MAX_PERIPH)
66 		return -EIO;
67 
68 	channel = priv->channel_map[usid][pid];
69 
70 	/* Disable IRQ mode for the current channel*/
71 	writel(0x0, priv->spmi_core + SPMI_CH_OFFSET(channel) +
72 	       SPMI_REG_CONFIG);
73 
74 	/* Write single byte */
75 	writel(val, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA);
76 
77 	/* Prepare write command */
78 	reg |= SPMI_CMD_EXT_REG_WRITE_LONG << SPMI_CMD_OPCODE_SHIFT;
79 	reg |= (usid << SPMI_CMD_SLAVE_ID_SHIFT);
80 	reg |= (pid << SPMI_CMD_ADDR_SHIFT);
81 	reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
82 	reg |= 1; /* byte count */
83 
84 	/* Send write command */
85 	writel(reg, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
86 
87 	/* Wait till CMD DONE status */
88 	reg = 0;
89 	while (!reg) {
90 		reg = readl(priv->spmi_core + SPMI_CH_OFFSET(channel) +
91 			    SPMI_REG_STATUS);
92 	}
93 
94 	if (reg ^ SPMI_STATUS_DONE) {
95 		printf("SPMI write failure.\n");
96 		return -EIO;
97 	}
98 
99 	return 0;
100 }
101 
102 static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
103 {
104 	struct msm_spmi_priv *priv = dev_get_priv(dev);
105 	unsigned channel;
106 	uint32_t reg = 0;
107 
108 	if (usid >= SPMI_MAX_SLAVES)
109 		return -EIO;
110 	if (pid >= SPMI_MAX_PERIPH)
111 		return -EIO;
112 
113 	channel = priv->channel_map[usid][pid];
114 
115 	/* Disable IRQ mode for the current channel*/
116 	writel(0x0, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
117 
118 	/* Prepare read command */
119 	reg |= SPMI_CMD_EXT_REG_READ_LONG << SPMI_CMD_OPCODE_SHIFT;
120 	reg |= (usid << SPMI_CMD_SLAVE_ID_SHIFT);
121 	reg |= (pid << SPMI_CMD_ADDR_SHIFT);
122 	reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
123 	reg |= 1; /* byte count */
124 
125 	/* Request read */
126 	writel(reg, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
127 
128 	/* Wait till CMD DONE status */
129 	reg = 0;
130 	while (!reg) {
131 		reg = readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) +
132 			    SPMI_REG_STATUS);
133 	}
134 
135 	if (reg ^ SPMI_STATUS_DONE) {
136 		printf("SPMI read failure.\n");
137 		return -EIO;
138 	}
139 
140 	/* Read the data */
141 	return readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) +
142 		     SPMI_REG_RDATA) & 0xFF;
143 }
144 
145 static struct dm_spmi_ops msm_spmi_ops = {
146 	.read = msm_spmi_read,
147 	.write = msm_spmi_write,
148 };
149 
150 static int msm_spmi_probe(struct udevice *dev)
151 {
152 	struct udevice *parent = dev->parent;
153 	struct msm_spmi_priv *priv = dev_get_priv(dev);
154 	int node = dev_of_offset(dev);
155 	u32 hw_ver;
156 	bool is_v1;
157 	int i;
158 
159 	priv->arb_chnl = devfdt_get_addr(dev);
160 	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
161 			dev_of_offset(parent), node, "reg", 1, NULL, false);
162 	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
163 			dev_of_offset(parent), node, "reg", 2, NULL, false);
164 
165 	hw_ver = readl(priv->arb_chnl + PMIC_ARB_VERSION - 0x800);
166 	is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);
167 
168 	dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", (is_v1 ? 1 : 2), hw_ver);
169 
170 	if (priv->arb_chnl == FDT_ADDR_T_NONE ||
171 	    priv->spmi_core == FDT_ADDR_T_NONE ||
172 	    priv->spmi_obs == FDT_ADDR_T_NONE)
173 		return -EINVAL;
174 
175 	/* Scan peripherals connected to each SPMI channel */
176 	for (i = 0; i < SPMI_MAX_PERIPH ; i++) {
177 		uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i));
178 		uint8_t slave_id = (periph & 0xf0000) >> 16;
179 		uint8_t pid = (periph & 0xff00) >> 8;
180 
181 		priv->channel_map[slave_id][pid] = i;
182 	}
183 	return 0;
184 }
185 
186 static const struct udevice_id msm_spmi_ids[] = {
187 	{ .compatible = "qcom,spmi-pmic-arb" },
188 	{ }
189 };
190 
191 U_BOOT_DRIVER(msm_spmi) = {
192 	.name = "msm_spmi",
193 	.id = UCLASS_SPMI,
194 	.of_match = msm_spmi_ids,
195 	.ops = &msm_spmi_ops,
196 	.probe = msm_spmi_probe,
197 	.priv_auto_alloc_size = sizeof(struct msm_spmi_priv),
198 };
199