1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2010, Google Inc. 4 * 5 * Original authors: Code Aurora Forum 6 * 7 * Author: Dima Zavin <dima@android.com> 8 * - Largely rewritten from original to not be an i2c driver. 9 */ 10 11 #define pr_fmt(fmt) "%s: " fmt, __func__ 12 13 #include <linux/delay.h> 14 #include <linux/err.h> 15 #include <linux/io.h> 16 #include <linux/kernel.h> 17 #include <linux/platform_device.h> 18 #include <linux/slab.h> 19 #include <linux/ssbi.h> 20 #include <linux/module.h> 21 #include <linux/of.h> 22 #include <linux/of_device.h> 23 24 /* SSBI 2.0 controller registers */ 25 #define SSBI2_CMD 0x0008 26 #define SSBI2_RD 0x0010 27 #define SSBI2_STATUS 0x0014 28 #define SSBI2_MODE2 0x001C 29 30 /* SSBI_CMD fields */ 31 #define SSBI_CMD_RDWRN (1 << 24) 32 33 /* SSBI_STATUS fields */ 34 #define SSBI_STATUS_RD_READY (1 << 2) 35 #define SSBI_STATUS_READY (1 << 1) 36 #define SSBI_STATUS_MCHN_BUSY (1 << 0) 37 38 /* SSBI_MODE2 fields */ 39 #define SSBI_MODE2_REG_ADDR_15_8_SHFT 0x04 40 #define SSBI_MODE2_REG_ADDR_15_8_MASK (0x7f << SSBI_MODE2_REG_ADDR_15_8_SHFT) 41 42 #define SET_SSBI_MODE2_REG_ADDR_15_8(MD, AD) \ 43 (((MD) & 0x0F) | ((((AD) >> 8) << SSBI_MODE2_REG_ADDR_15_8_SHFT) & \ 44 SSBI_MODE2_REG_ADDR_15_8_MASK)) 45 46 /* SSBI PMIC Arbiter command registers */ 47 #define SSBI_PA_CMD 0x0000 48 #define SSBI_PA_RD_STATUS 0x0004 49 50 /* SSBI_PA_CMD fields */ 51 #define SSBI_PA_CMD_RDWRN (1 << 24) 52 #define SSBI_PA_CMD_ADDR_MASK 0x7fff /* REG_ADDR_7_0, REG_ADDR_8_14*/ 53 54 /* SSBI_PA_RD_STATUS fields */ 55 #define SSBI_PA_RD_STATUS_TRANS_DONE (1 << 27) 56 #define SSBI_PA_RD_STATUS_TRANS_DENIED (1 << 26) 57 58 #define SSBI_TIMEOUT_US 100 59 60 enum ssbi_controller_type { 61 MSM_SBI_CTRL_SSBI = 0, 62 MSM_SBI_CTRL_SSBI2, 63 MSM_SBI_CTRL_PMIC_ARBITER, 64 }; 65 66 struct ssbi { 67 struct device *slave; 68 void __iomem *base; 69 spinlock_t lock; 70 enum ssbi_controller_type controller_type; 71 int (*read)(struct ssbi *, u16 addr, u8 *buf, int len); 72 int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len); 73 }; 74 75 static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg) 76 { 77 return readl(ssbi->base + reg); 78 } 79 80 static inline void ssbi_writel(struct ssbi *ssbi, u32 val, u32 reg) 81 { 82 writel(val, ssbi->base + reg); 83 } 84 85 /* 86 * Via private exchange with one of the original authors, the hardware 87 * should generally finish a transaction in about 5us. The worst 88 * case, is when using the arbiter and both other CPUs have just 89 * started trying to use the SSBI bus will result in a time of about 90 * 20us. It should never take longer than this. 91 * 92 * As such, this wait merely spins, with a udelay. 93 */ 94 static int ssbi_wait_mask(struct ssbi *ssbi, u32 set_mask, u32 clr_mask) 95 { 96 u32 timeout = SSBI_TIMEOUT_US; 97 u32 val; 98 99 while (timeout--) { 100 val = ssbi_readl(ssbi, SSBI2_STATUS); 101 if (((val & set_mask) == set_mask) && ((val & clr_mask) == 0)) 102 return 0; 103 udelay(1); 104 } 105 106 return -ETIMEDOUT; 107 } 108 109 static int 110 ssbi_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) 111 { 112 u32 cmd = SSBI_CMD_RDWRN | ((addr & 0xff) << 16); 113 int ret = 0; 114 115 if (ssbi->controller_type == MSM_SBI_CTRL_SSBI2) { 116 u32 mode2 = ssbi_readl(ssbi, SSBI2_MODE2); 117 mode2 = SET_SSBI_MODE2_REG_ADDR_15_8(mode2, addr); 118 ssbi_writel(ssbi, mode2, SSBI2_MODE2); 119 } 120 121 while (len) { 122 ret = ssbi_wait_mask(ssbi, SSBI_STATUS_READY, 0); 123 if (ret) 124 goto err; 125 126 ssbi_writel(ssbi, cmd, SSBI2_CMD); 127 ret = ssbi_wait_mask(ssbi, SSBI_STATUS_RD_READY, 0); 128 if (ret) 129 goto err; 130 *buf++ = ssbi_readl(ssbi, SSBI2_RD) & 0xff; 131 len--; 132 } 133 134 err: 135 return ret; 136 } 137 138 static int 139 ssbi_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len) 140 { 141 int ret = 0; 142 143 if (ssbi->controller_type == MSM_SBI_CTRL_SSBI2) { 144 u32 mode2 = ssbi_readl(ssbi, SSBI2_MODE2); 145 mode2 = SET_SSBI_MODE2_REG_ADDR_15_8(mode2, addr); 146 ssbi_writel(ssbi, mode2, SSBI2_MODE2); 147 } 148 149 while (len) { 150 ret = ssbi_wait_mask(ssbi, SSBI_STATUS_READY, 0); 151 if (ret) 152 goto err; 153 154 ssbi_writel(ssbi, ((addr & 0xff) << 16) | *buf, SSBI2_CMD); 155 ret = ssbi_wait_mask(ssbi, 0, SSBI_STATUS_MCHN_BUSY); 156 if (ret) 157 goto err; 158 buf++; 159 len--; 160 } 161 162 err: 163 return ret; 164 } 165 166 /* 167 * See ssbi_wait_mask for an explanation of the time and the 168 * busywait. 169 */ 170 static inline int 171 ssbi_pa_transfer(struct ssbi *ssbi, u32 cmd, u8 *data) 172 { 173 u32 timeout = SSBI_TIMEOUT_US; 174 u32 rd_status = 0; 175 176 ssbi_writel(ssbi, cmd, SSBI_PA_CMD); 177 178 while (timeout--) { 179 rd_status = ssbi_readl(ssbi, SSBI_PA_RD_STATUS); 180 181 if (rd_status & SSBI_PA_RD_STATUS_TRANS_DENIED) 182 return -EPERM; 183 184 if (rd_status & SSBI_PA_RD_STATUS_TRANS_DONE) { 185 if (data) 186 *data = rd_status & 0xff; 187 return 0; 188 } 189 udelay(1); 190 } 191 192 return -ETIMEDOUT; 193 } 194 195 static int 196 ssbi_pa_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len) 197 { 198 u32 cmd; 199 int ret = 0; 200 201 cmd = SSBI_PA_CMD_RDWRN | (addr & SSBI_PA_CMD_ADDR_MASK) << 8; 202 203 while (len) { 204 ret = ssbi_pa_transfer(ssbi, cmd, buf); 205 if (ret) 206 goto err; 207 buf++; 208 len--; 209 } 210 211 err: 212 return ret; 213 } 214 215 static int 216 ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len) 217 { 218 u32 cmd; 219 int ret = 0; 220 221 while (len) { 222 cmd = (addr & SSBI_PA_CMD_ADDR_MASK) << 8 | *buf; 223 ret = ssbi_pa_transfer(ssbi, cmd, NULL); 224 if (ret) 225 goto err; 226 buf++; 227 len--; 228 } 229 230 err: 231 return ret; 232 } 233 234 int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len) 235 { 236 struct ssbi *ssbi = dev_get_drvdata(dev); 237 unsigned long flags; 238 int ret; 239 240 spin_lock_irqsave(&ssbi->lock, flags); 241 ret = ssbi->read(ssbi, addr, buf, len); 242 spin_unlock_irqrestore(&ssbi->lock, flags); 243 244 return ret; 245 } 246 EXPORT_SYMBOL_GPL(ssbi_read); 247 248 int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len) 249 { 250 struct ssbi *ssbi = dev_get_drvdata(dev); 251 unsigned long flags; 252 int ret; 253 254 spin_lock_irqsave(&ssbi->lock, flags); 255 ret = ssbi->write(ssbi, addr, buf, len); 256 spin_unlock_irqrestore(&ssbi->lock, flags); 257 258 return ret; 259 } 260 EXPORT_SYMBOL_GPL(ssbi_write); 261 262 static int ssbi_probe(struct platform_device *pdev) 263 { 264 struct device_node *np = pdev->dev.of_node; 265 struct resource *mem_res; 266 struct ssbi *ssbi; 267 const char *type; 268 269 ssbi = devm_kzalloc(&pdev->dev, sizeof(*ssbi), GFP_KERNEL); 270 if (!ssbi) 271 return -ENOMEM; 272 273 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 274 ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res); 275 if (IS_ERR(ssbi->base)) 276 return PTR_ERR(ssbi->base); 277 278 platform_set_drvdata(pdev, ssbi); 279 280 type = of_get_property(np, "qcom,controller-type", NULL); 281 if (type == NULL) { 282 dev_err(&pdev->dev, "Missing qcom,controller-type property\n"); 283 return -EINVAL; 284 } 285 dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type); 286 if (strcmp(type, "ssbi") == 0) 287 ssbi->controller_type = MSM_SBI_CTRL_SSBI; 288 else if (strcmp(type, "ssbi2") == 0) 289 ssbi->controller_type = MSM_SBI_CTRL_SSBI2; 290 else if (strcmp(type, "pmic-arbiter") == 0) 291 ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER; 292 else { 293 dev_err(&pdev->dev, "Unknown qcom,controller-type\n"); 294 return -EINVAL; 295 } 296 297 if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) { 298 ssbi->read = ssbi_pa_read_bytes; 299 ssbi->write = ssbi_pa_write_bytes; 300 } else { 301 ssbi->read = ssbi_read_bytes; 302 ssbi->write = ssbi_write_bytes; 303 } 304 305 spin_lock_init(&ssbi->lock); 306 307 return devm_of_platform_populate(&pdev->dev); 308 } 309 310 static const struct of_device_id ssbi_match_table[] = { 311 { .compatible = "qcom,ssbi" }, 312 {} 313 }; 314 MODULE_DEVICE_TABLE(of, ssbi_match_table); 315 316 static struct platform_driver ssbi_driver = { 317 .probe = ssbi_probe, 318 .driver = { 319 .name = "ssbi", 320 .of_match_table = ssbi_match_table, 321 }, 322 }; 323 module_platform_driver(ssbi_driver); 324 325 MODULE_LICENSE("GPL v2"); 326 MODULE_VERSION("1.0"); 327 MODULE_ALIAS("platform:ssbi"); 328 MODULE_AUTHOR("Dima Zavin <dima@android.com>"); 329