Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.6-rc2 469 lines 12 kB view raw
1/* 2 * Rockchip IO Voltage Domain driver 3 * 4 * Copyright 2014 MundoReader S.L. 5 * Copyright 2014 Google, Inc. 6 * 7 * This software is licensed under the terms of the GNU General Public 8 * License version 2, as published by the Free Software Foundation, and 9 * may be copied, distributed, and modified under those terms. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/err.h> 20#include <linux/mfd/syscon.h> 21#include <linux/of.h> 22#include <linux/platform_device.h> 23#include <linux/regmap.h> 24#include <linux/regulator/consumer.h> 25 26#define MAX_SUPPLIES 16 27 28/* 29 * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under 30 * "Recommended Operating Conditions" for "Digital GPIO". When the typical 31 * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V. 32 * 33 * They are used like this: 34 * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the 35 * SoC we're at 3.3. 36 * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider 37 * that to be an error. 38 */ 39#define MAX_VOLTAGE_1_8 1980000 40#define MAX_VOLTAGE_3_3 3600000 41 42#define RK3288_SOC_CON2 0x24c 43#define RK3288_SOC_CON2_FLASH0 BIT(7) 44#define RK3288_SOC_FLASH_SUPPLY_NUM 2 45 46#define RK3368_SOC_CON15 0x43c 47#define RK3368_SOC_CON15_FLASH0 BIT(14) 48#define RK3368_SOC_FLASH_SUPPLY_NUM 2 49 50#define RK3399_PMUGRF_CON0 0x180 51#define RK3399_PMUGRF_CON0_VSEL BIT(8) 52#define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9 53 54struct rockchip_iodomain; 55 56/** 57 * @supplies: voltage settings matching the register bits. 58 */ 59struct rockchip_iodomain_soc_data { 60 int grf_offset; 61 const char *supply_names[MAX_SUPPLIES]; 62 void (*init)(struct rockchip_iodomain *iod); 63}; 64 65struct rockchip_iodomain_supply { 66 struct rockchip_iodomain *iod; 67 struct regulator *reg; 68 struct notifier_block nb; 69 int idx; 70}; 71 72struct rockchip_iodomain { 73 struct device *dev; 74 struct regmap *grf; 75 struct rockchip_iodomain_soc_data *soc_data; 76 struct rockchip_iodomain_supply supplies[MAX_SUPPLIES]; 77}; 78 79static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply, 80 int uV) 81{ 82 struct rockchip_iodomain *iod = supply->iod; 83 u32 val; 84 int ret; 85 86 /* set value bit */ 87 val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1; 88 val <<= supply->idx; 89 90 /* apply hiword-mask */ 91 val |= (BIT(supply->idx) << 16); 92 93 ret = regmap_write(iod->grf, iod->soc_data->grf_offset, val); 94 if (ret) 95 dev_err(iod->dev, "Couldn't write to GRF\n"); 96 97 return ret; 98} 99 100static int rockchip_iodomain_notify(struct notifier_block *nb, 101 unsigned long event, 102 void *data) 103{ 104 struct rockchip_iodomain_supply *supply = 105 container_of(nb, struct rockchip_iodomain_supply, nb); 106 int uV; 107 int ret; 108 109 /* 110 * According to Rockchip it's important to keep the SoC IO domain 111 * higher than (or equal to) the external voltage. That means we need 112 * to change it before external voltage changes happen in the case 113 * of an increase. 114 * 115 * Note that in the "pre" change we pick the max possible voltage that 116 * the regulator might end up at (the client requests a range and we 117 * don't know for certain the exact voltage). Right now we rely on the 118 * slop in MAX_VOLTAGE_1_8 and MAX_VOLTAGE_3_3 to save us if clients 119 * request something like a max of 3.6V when they really want 3.3V. 120 * We could attempt to come up with better rules if this fails. 121 */ 122 if (event & REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) { 123 struct pre_voltage_change_data *pvc_data = data; 124 125 uV = max_t(unsigned long, pvc_data->old_uV, pvc_data->max_uV); 126 } else if (event & (REGULATOR_EVENT_VOLTAGE_CHANGE | 127 REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE)) { 128 uV = (unsigned long)data; 129 } else { 130 return NOTIFY_OK; 131 } 132 133 dev_dbg(supply->iod->dev, "Setting to %d\n", uV); 134 135 if (uV > MAX_VOLTAGE_3_3) { 136 dev_err(supply->iod->dev, "Voltage too high: %d\n", uV); 137 138 if (event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) 139 return NOTIFY_BAD; 140 } 141 142 ret = rockchip_iodomain_write(supply, uV); 143 if (ret && event == REGULATOR_EVENT_PRE_VOLTAGE_CHANGE) 144 return NOTIFY_BAD; 145 146 dev_info(supply->iod->dev, "Setting to %d done\n", uV); 147 return NOTIFY_OK; 148} 149 150static void rk3288_iodomain_init(struct rockchip_iodomain *iod) 151{ 152 int ret; 153 u32 val; 154 155 /* if no flash supply we should leave things alone */ 156 if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg) 157 return; 158 159 /* 160 * set flash0 iodomain to also use this framework 161 * instead of a special gpio. 162 */ 163 val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16); 164 ret = regmap_write(iod->grf, RK3288_SOC_CON2, val); 165 if (ret < 0) 166 dev_warn(iod->dev, "couldn't update flash0 ctrl\n"); 167} 168 169static void rk3368_iodomain_init(struct rockchip_iodomain *iod) 170{ 171 int ret; 172 u32 val; 173 174 /* if no flash supply we should leave things alone */ 175 if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg) 176 return; 177 178 /* 179 * set flash0 iodomain to also use this framework 180 * instead of a special gpio. 181 */ 182 val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16); 183 ret = regmap_write(iod->grf, RK3368_SOC_CON15, val); 184 if (ret < 0) 185 dev_warn(iod->dev, "couldn't update flash0 ctrl\n"); 186} 187 188static void rk3399_pmu_iodomain_init(struct rockchip_iodomain *iod) 189{ 190 int ret; 191 u32 val; 192 193 /* if no pmu io supply we should leave things alone */ 194 if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg) 195 return; 196 197 /* 198 * set pmu io iodomain to also use this framework 199 * instead of a special gpio. 200 */ 201 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16); 202 ret = regmap_write(iod->grf, RK3399_PMUGRF_CON0, val); 203 if (ret < 0) 204 dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n"); 205} 206 207/* 208 * On the rk3188 the io-domains are handled by a shared register with the 209 * lower 8 bits being still being continuing drive-strength settings. 210 */ 211static const struct rockchip_iodomain_soc_data soc_data_rk3188 = { 212 .grf_offset = 0x104, 213 .supply_names = { 214 NULL, 215 NULL, 216 NULL, 217 NULL, 218 NULL, 219 NULL, 220 NULL, 221 NULL, 222 "ap0", 223 "ap1", 224 "cif", 225 "flash", 226 "vccio0", 227 "vccio1", 228 "lcdc0", 229 "lcdc1", 230 }, 231}; 232 233static const struct rockchip_iodomain_soc_data soc_data_rk3288 = { 234 .grf_offset = 0x380, 235 .supply_names = { 236 "lcdc", /* LCDC_VDD */ 237 "dvp", /* DVPIO_VDD */ 238 "flash0", /* FLASH0_VDD (emmc) */ 239 "flash1", /* FLASH1_VDD (sdio1) */ 240 "wifi", /* APIO3_VDD (sdio0) */ 241 "bb", /* APIO5_VDD */ 242 "audio", /* APIO4_VDD */ 243 "sdcard", /* SDMMC0_VDD (sdmmc) */ 244 "gpio30", /* APIO1_VDD */ 245 "gpio1830", /* APIO2_VDD */ 246 }, 247 .init = rk3288_iodomain_init, 248}; 249 250static const struct rockchip_iodomain_soc_data soc_data_rk3368 = { 251 .grf_offset = 0x900, 252 .supply_names = { 253 NULL, /* reserved */ 254 "dvp", /* DVPIO_VDD */ 255 "flash0", /* FLASH0_VDD (emmc) */ 256 "wifi", /* APIO2_VDD (sdio0) */ 257 NULL, 258 "audio", /* APIO3_VDD */ 259 "sdcard", /* SDMMC0_VDD (sdmmc) */ 260 "gpio30", /* APIO1_VDD */ 261 "gpio1830", /* APIO4_VDD (gpujtag) */ 262 }, 263 .init = rk3368_iodomain_init, 264}; 265 266static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = { 267 .grf_offset = 0x100, 268 .supply_names = { 269 NULL, 270 NULL, 271 NULL, 272 NULL, 273 "pmu", /*PMU IO domain*/ 274 "vop", /*LCDC IO domain*/ 275 }, 276}; 277 278static const struct rockchip_iodomain_soc_data soc_data_rk3399 = { 279 .grf_offset = 0xe640, 280 .supply_names = { 281 "bt656", /* APIO2_VDD */ 282 "audio", /* APIO5_VDD */ 283 "sdmmc", /* SDMMC0_VDD */ 284 "gpio1830", /* APIO4_VDD */ 285 }, 286}; 287 288static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = { 289 .grf_offset = 0x180, 290 .supply_names = { 291 NULL, 292 NULL, 293 NULL, 294 NULL, 295 NULL, 296 NULL, 297 NULL, 298 NULL, 299 NULL, 300 "pmu1830", /* PMUIO2_VDD */ 301 }, 302 .init = rk3399_pmu_iodomain_init, 303}; 304 305static const struct of_device_id rockchip_iodomain_match[] = { 306 { 307 .compatible = "rockchip,rk3188-io-voltage-domain", 308 .data = (void *)&soc_data_rk3188 309 }, 310 { 311 .compatible = "rockchip,rk3288-io-voltage-domain", 312 .data = (void *)&soc_data_rk3288 313 }, 314 { 315 .compatible = "rockchip,rk3368-io-voltage-domain", 316 .data = (void *)&soc_data_rk3368 317 }, 318 { 319 .compatible = "rockchip,rk3368-pmu-io-voltage-domain", 320 .data = (void *)&soc_data_rk3368_pmu 321 }, 322 { 323 .compatible = "rockchip,rk3399-io-voltage-domain", 324 .data = (void *)&soc_data_rk3399 325 }, 326 { 327 .compatible = "rockchip,rk3399-pmu-io-voltage-domain", 328 .data = (void *)&soc_data_rk3399_pmu 329 }, 330 { /* sentinel */ }, 331}; 332MODULE_DEVICE_TABLE(of, rockchip_iodomain_match); 333 334static int rockchip_iodomain_probe(struct platform_device *pdev) 335{ 336 struct device_node *np = pdev->dev.of_node; 337 const struct of_device_id *match; 338 struct rockchip_iodomain *iod; 339 int i, ret = 0; 340 341 if (!np) 342 return -ENODEV; 343 344 iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL); 345 if (!iod) 346 return -ENOMEM; 347 348 iod->dev = &pdev->dev; 349 platform_set_drvdata(pdev, iod); 350 351 match = of_match_node(rockchip_iodomain_match, np); 352 iod->soc_data = (struct rockchip_iodomain_soc_data *)match->data; 353 354 iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 355 if (IS_ERR(iod->grf)) { 356 dev_err(&pdev->dev, "couldn't find grf regmap\n"); 357 return PTR_ERR(iod->grf); 358 } 359 360 for (i = 0; i < MAX_SUPPLIES; i++) { 361 const char *supply_name = iod->soc_data->supply_names[i]; 362 struct rockchip_iodomain_supply *supply = &iod->supplies[i]; 363 struct regulator *reg; 364 int uV; 365 366 if (!supply_name) 367 continue; 368 369 reg = devm_regulator_get_optional(iod->dev, supply_name); 370 if (IS_ERR(reg)) { 371 ret = PTR_ERR(reg); 372 373 /* If a supply wasn't specified, that's OK */ 374 if (ret == -ENODEV) 375 continue; 376 else if (ret != -EPROBE_DEFER) 377 dev_err(iod->dev, "couldn't get regulator %s\n", 378 supply_name); 379 goto unreg_notify; 380 } 381 382 /* set initial correct value */ 383 uV = regulator_get_voltage(reg); 384 385 /* must be a regulator we can get the voltage of */ 386 if (uV < 0) { 387 dev_err(iod->dev, "Can't determine voltage: %s\n", 388 supply_name); 389 goto unreg_notify; 390 } 391 392 if (uV > MAX_VOLTAGE_3_3) { 393 dev_crit(iod->dev, 394 "%d uV is too high. May damage SoC!\n", 395 uV); 396 ret = -EINVAL; 397 goto unreg_notify; 398 } 399 400 /* setup our supply */ 401 supply->idx = i; 402 supply->iod = iod; 403 supply->reg = reg; 404 supply->nb.notifier_call = rockchip_iodomain_notify; 405 406 ret = rockchip_iodomain_write(supply, uV); 407 if (ret) { 408 supply->reg = NULL; 409 goto unreg_notify; 410 } 411 412 /* register regulator notifier */ 413 ret = regulator_register_notifier(reg, &supply->nb); 414 if (ret) { 415 dev_err(&pdev->dev, 416 "regulator notifier request failed\n"); 417 supply->reg = NULL; 418 goto unreg_notify; 419 } 420 } 421 422 if (iod->soc_data->init) 423 iod->soc_data->init(iod); 424 425 return 0; 426 427unreg_notify: 428 for (i = MAX_SUPPLIES - 1; i >= 0; i--) { 429 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i]; 430 431 if (io_supply->reg) 432 regulator_unregister_notifier(io_supply->reg, 433 &io_supply->nb); 434 } 435 436 return ret; 437} 438 439static int rockchip_iodomain_remove(struct platform_device *pdev) 440{ 441 struct rockchip_iodomain *iod = platform_get_drvdata(pdev); 442 int i; 443 444 for (i = MAX_SUPPLIES - 1; i >= 0; i--) { 445 struct rockchip_iodomain_supply *io_supply = &iod->supplies[i]; 446 447 if (io_supply->reg) 448 regulator_unregister_notifier(io_supply->reg, 449 &io_supply->nb); 450 } 451 452 return 0; 453} 454 455static struct platform_driver rockchip_iodomain_driver = { 456 .probe = rockchip_iodomain_probe, 457 .remove = rockchip_iodomain_remove, 458 .driver = { 459 .name = "rockchip-iodomain", 460 .of_match_table = rockchip_iodomain_match, 461 }, 462}; 463 464module_platform_driver(rockchip_iodomain_driver); 465 466MODULE_DESCRIPTION("Rockchip IO-domain driver"); 467MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 468MODULE_AUTHOR("Doug Anderson <dianders@chromium.org>"); 469MODULE_LICENSE("GPL v2");