sandbox.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2011 The Chromium OS Authors.
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <fdtdec.h>
  8. #include <log.h>
  9. #include <malloc.h>
  10. #include <acpi/acpi_device.h>
  11. #include <asm/gpio.h>
  12. #include <dm/acpi.h>
  13. #include <dm/device-internal.h>
  14. #include <dm/device_compat.h>
  15. #include <dm/lists.h>
  16. #include <dm/of.h>
  17. #include <dm/pinctrl.h>
  18. #include <dt-bindings/gpio/gpio.h>
  19. #include <dt-bindings/gpio/sandbox-gpio.h>
  20. struct gpio_state {
  21. const char *label; /* label given by requester */
  22. ulong flags; /* flags (GPIOD_...) */
  23. };
  24. /* Access routines for GPIO info */
  25. static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset)
  26. {
  27. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  28. struct gpio_state *state = dev_get_priv(dev);
  29. if (offset >= uc_priv->gpio_count) {
  30. printf("sandbox_gpio: error: invalid gpio %u\n", offset);
  31. return NULL;
  32. }
  33. return &state[offset];
  34. }
  35. /* Access routines for GPIO flags */
  36. static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset)
  37. {
  38. struct gpio_state *state = get_gpio_state(dev, offset);
  39. if (!state)
  40. return NULL;
  41. return &state->flags;
  42. }
  43. static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
  44. {
  45. return (*get_gpio_flags(dev, offset) & flag) != 0;
  46. }
  47. static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
  48. int value)
  49. {
  50. struct gpio_state *state = get_gpio_state(dev, offset);
  51. if (value)
  52. state->flags |= flag;
  53. else
  54. state->flags &= ~flag;
  55. return 0;
  56. }
  57. /*
  58. * Back-channel sandbox-internal-only access to GPIO state
  59. */
  60. int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
  61. {
  62. struct gpio_state *state = get_gpio_state(dev, offset);
  63. bool val;
  64. if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
  65. debug("sandbox_gpio: get_value on output gpio %u\n", offset);
  66. if (state->flags & GPIOD_EXT_DRIVEN) {
  67. val = state->flags & GPIOD_EXT_HIGH;
  68. } else {
  69. if (state->flags & GPIOD_EXT_PULL_UP)
  70. val = true;
  71. else if (state->flags & GPIOD_EXT_PULL_DOWN)
  72. val = false;
  73. else
  74. val = state->flags & GPIOD_PULL_UP;
  75. }
  76. return val;
  77. }
  78. int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
  79. {
  80. set_gpio_flag(dev, offset, GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
  81. return 0;
  82. }
  83. int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
  84. {
  85. return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
  86. }
  87. int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
  88. {
  89. set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
  90. set_gpio_flag(dev, offset, GPIOD_IS_IN, !output);
  91. return 0;
  92. }
  93. ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset)
  94. {
  95. ulong flags = *get_gpio_flags(dev, offset);
  96. return flags & ~GPIOD_SANDBOX_MASK;
  97. }
  98. int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags)
  99. {
  100. struct gpio_state *state = get_gpio_state(dev, offset);
  101. state->flags = flags;
  102. return 0;
  103. }
  104. /*
  105. * These functions implement the public interface within U-Boot
  106. */
  107. /* set GPIO port 'offset' as an input */
  108. static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
  109. {
  110. debug("%s: offset:%u\n", __func__, offset);
  111. return sandbox_gpio_set_direction(dev, offset, 0);
  112. }
  113. /* set GPIO port 'offset' as an output, with polarity 'value' */
  114. static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
  115. int value)
  116. {
  117. int ret;
  118. debug("%s: offset:%u, value = %d\n", __func__, offset, value);
  119. ret = sandbox_gpio_set_direction(dev, offset, 1);
  120. if (ret)
  121. return ret;
  122. ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
  123. GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
  124. if (ret)
  125. return ret;
  126. return 0;
  127. }
  128. /* read GPIO IN value of port 'offset' */
  129. static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
  130. {
  131. debug("%s: offset:%u\n", __func__, offset);
  132. return sandbox_gpio_get_value(dev, offset);
  133. }
  134. /* write GPIO OUT value to port 'offset' */
  135. static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
  136. {
  137. int ret;
  138. debug("%s: offset:%u, value = %d\n", __func__, offset, value);
  139. if (!sandbox_gpio_get_direction(dev, offset)) {
  140. printf("sandbox_gpio: error: set_value on input gpio %u\n",
  141. offset);
  142. return -1;
  143. }
  144. ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE |
  145. GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value);
  146. if (ret)
  147. return ret;
  148. return 0;
  149. }
  150. static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
  151. {
  152. if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
  153. return GPIOF_OUTPUT;
  154. if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
  155. return GPIOF_INPUT;
  156. if (get_gpio_flag(dev, offset, GPIOD_IS_AF))
  157. return GPIOF_FUNC;
  158. return GPIOF_INPUT; /*GPIO is not configurated */
  159. }
  160. static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
  161. struct ofnode_phandle_args *args)
  162. {
  163. desc->offset = args->args[0];
  164. if (args->args_count < 2)
  165. return 0;
  166. /* treat generic binding with gpio uclass */
  167. gpio_xlate_offs_flags(dev, desc, args);
  168. /* sandbox test specific, not defined in gpio.h */
  169. if (args->args[1] & GPIO_IN)
  170. desc->flags |= GPIOD_IS_IN;
  171. if (args->args[1] & GPIO_OUT)
  172. desc->flags |= GPIOD_IS_OUT;
  173. if (args->args[1] & GPIO_OUT_ACTIVE)
  174. desc->flags |= GPIOD_IS_OUT_ACTIVE;
  175. if (args->args[1] & GPIO_AF)
  176. desc->flags |= GPIOD_IS_AF;
  177. return 0;
  178. }
  179. static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset,
  180. ulong flags)
  181. {
  182. debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags);
  183. struct gpio_state *state = get_gpio_state(dev, offset);
  184. if (flags & GPIOD_IS_OUT) {
  185. flags |= GPIOD_EXT_DRIVEN;
  186. if (flags & GPIOD_IS_OUT_ACTIVE)
  187. flags |= GPIOD_EXT_HIGH;
  188. else
  189. flags &= ~GPIOD_EXT_HIGH;
  190. } else {
  191. flags |= state->flags & GPIOD_SANDBOX_MASK;
  192. }
  193. state->flags = flags;
  194. return 0;
  195. }
  196. static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp)
  197. {
  198. debug("%s: offset:%u\n", __func__, offset);
  199. *flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK;
  200. return 0;
  201. }
  202. #if CONFIG_IS_ENABLED(ACPIGEN)
  203. static int sb_gpio_get_acpi(const struct gpio_desc *desc,
  204. struct acpi_gpio *gpio)
  205. {
  206. int ret;
  207. /* Note that gpio_get_acpi() zeroes *gpio before calling here */
  208. gpio->pin_count = 1;
  209. gpio->pins[0] = desc->offset;
  210. ret = acpi_device_scope(desc->dev, gpio->resource,
  211. sizeof(gpio->resource));
  212. if (ret)
  213. return log_ret(ret);
  214. /* All of these values are just used for testing */
  215. if (desc->flags & GPIOD_ACTIVE_LOW) {
  216. gpio->pin0_addr = 0x80012 + desc->offset;
  217. gpio->type = ACPI_GPIO_TYPE_INTERRUPT;
  218. gpio->pull = ACPI_GPIO_PULL_DOWN;
  219. gpio->interrupt_debounce_timeout = 4321;
  220. /* We use the GpioInt part */
  221. gpio->irq.pin = desc->offset;
  222. gpio->irq.polarity = ACPI_IRQ_ACTIVE_BOTH;
  223. gpio->irq.shared = ACPI_IRQ_SHARED;
  224. gpio->irq.wake = ACPI_IRQ_WAKE;
  225. /* The GpioIo part is only used for testing */
  226. gpio->polarity = ACPI_GPIO_ACTIVE_LOW;
  227. } else {
  228. gpio->pin0_addr = 0xc00dc + desc->offset;
  229. gpio->type = ACPI_GPIO_TYPE_IO;
  230. gpio->pull = ACPI_GPIO_PULL_UP;
  231. gpio->interrupt_debounce_timeout = 0;
  232. /* The GpioInt part is not used */
  233. /* We use the GpioIo part */
  234. gpio->output_drive_strength = 1234;
  235. gpio->io_shared = true;
  236. gpio->io_restrict = ACPI_GPIO_IO_RESTRICT_INPUT;
  237. gpio->polarity = 0;
  238. }
  239. return 0;
  240. }
  241. static int sb_gpio_get_name(const struct udevice *dev, char *out_name)
  242. {
  243. return acpi_copy_name(out_name, "GPIO");
  244. }
  245. struct acpi_ops gpio_sandbox_acpi_ops = {
  246. .get_name = sb_gpio_get_name,
  247. };
  248. #endif /* ACPIGEN */
  249. static const struct dm_gpio_ops gpio_sandbox_ops = {
  250. .direction_input = sb_gpio_direction_input,
  251. .direction_output = sb_gpio_direction_output,
  252. .get_value = sb_gpio_get_value,
  253. .set_value = sb_gpio_set_value,
  254. .get_function = sb_gpio_get_function,
  255. .xlate = sb_gpio_xlate,
  256. .set_flags = sb_gpio_set_flags,
  257. .get_flags = sb_gpio_get_flags,
  258. #if CONFIG_IS_ENABLED(ACPIGEN)
  259. .get_acpi = sb_gpio_get_acpi,
  260. #endif
  261. };
  262. static int sandbox_gpio_of_to_plat(struct udevice *dev)
  263. {
  264. if (CONFIG_IS_ENABLED(OF_REAL)) {
  265. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  266. uc_priv->gpio_count =
  267. dev_read_u32_default(dev, "sandbox,gpio-count", 0);
  268. uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
  269. }
  270. return 0;
  271. }
  272. static int gpio_sandbox_probe(struct udevice *dev)
  273. {
  274. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  275. if (!dev_has_ofnode(dev))
  276. /* Tell the uclass how many GPIOs we have */
  277. uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
  278. dev_set_priv(dev,
  279. calloc(sizeof(struct gpio_state), uc_priv->gpio_count));
  280. return 0;
  281. }
  282. static int gpio_sandbox_remove(struct udevice *dev)
  283. {
  284. free(dev_get_priv(dev));
  285. return 0;
  286. }
  287. static const struct udevice_id sandbox_gpio_ids[] = {
  288. { .compatible = "sandbox,gpio" },
  289. { }
  290. };
  291. U_BOOT_DRIVER(sandbox_gpio) = {
  292. .name = "sandbox_gpio",
  293. .id = UCLASS_GPIO,
  294. .of_match = sandbox_gpio_ids,
  295. .of_to_plat = sandbox_gpio_of_to_plat,
  296. .probe = gpio_sandbox_probe,
  297. .remove = gpio_sandbox_remove,
  298. .ops = &gpio_sandbox_ops,
  299. ACPI_OPS_PTR(&gpio_sandbox_acpi_ops)
  300. };
  301. DM_DRIVER_ALIAS(sandbox_gpio, sandbox_gpio_alias)
  302. #if CONFIG_IS_ENABLED(PINCTRL)
  303. /* pincontrol: used only to check GPIO pin configuration (pinmux command) */
  304. struct sb_pinctrl_priv {
  305. int pinctrl_ngpios;
  306. struct list_head gpio_dev;
  307. };
  308. struct sb_gpio_bank {
  309. struct udevice *gpio_dev;
  310. struct list_head list;
  311. };
  312. static int sb_populate_gpio_dev_list(struct udevice *dev)
  313. {
  314. struct sb_pinctrl_priv *priv = dev_get_priv(dev);
  315. struct udevice *gpio_dev;
  316. struct udevice *child;
  317. struct sb_gpio_bank *gpio_bank;
  318. int ret;
  319. /*
  320. * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
  321. * a list with all gpio device reference which belongs to the
  322. * current pin-controller. This list is used to find pin_name and
  323. * pin muxing
  324. */
  325. list_for_each_entry(child, &dev->child_head, sibling_node) {
  326. ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
  327. &gpio_dev);
  328. if (ret < 0)
  329. continue;
  330. gpio_bank = malloc(sizeof(*gpio_bank));
  331. if (!gpio_bank) {
  332. dev_err(dev, "Not enough memory\n");
  333. return -ENOMEM;
  334. }
  335. gpio_bank->gpio_dev = gpio_dev;
  336. list_add_tail(&gpio_bank->list, &priv->gpio_dev);
  337. }
  338. return 0;
  339. }
  340. static int sb_pinctrl_get_pins_count(struct udevice *dev)
  341. {
  342. struct sb_pinctrl_priv *priv = dev_get_priv(dev);
  343. struct gpio_dev_priv *uc_priv;
  344. struct sb_gpio_bank *gpio_bank;
  345. /*
  346. * if get_pins_count has already been executed once on this
  347. * pin-controller, no need to run it again
  348. */
  349. if (priv->pinctrl_ngpios)
  350. return priv->pinctrl_ngpios;
  351. if (list_empty(&priv->gpio_dev))
  352. sb_populate_gpio_dev_list(dev);
  353. /*
  354. * walk through all banks to retrieve the pin-controller
  355. * pins number
  356. */
  357. list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
  358. uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
  359. priv->pinctrl_ngpios += uc_priv->gpio_count;
  360. }
  361. return priv->pinctrl_ngpios;
  362. }
  363. static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
  364. unsigned int selector,
  365. unsigned int *idx)
  366. {
  367. struct sb_pinctrl_priv *priv = dev_get_priv(dev);
  368. struct sb_gpio_bank *gpio_bank;
  369. struct gpio_dev_priv *uc_priv;
  370. int pin_count = 0;
  371. if (list_empty(&priv->gpio_dev))
  372. sb_populate_gpio_dev_list(dev);
  373. /* look up for the bank which owns the requested pin */
  374. list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
  375. uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
  376. if (selector < (pin_count + uc_priv->gpio_count)) {
  377. /*
  378. * we found the bank, convert pin selector to
  379. * gpio bank index
  380. */
  381. *idx = selector - pin_count;
  382. return gpio_bank->gpio_dev;
  383. }
  384. pin_count += uc_priv->gpio_count;
  385. }
  386. return NULL;
  387. }
  388. static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
  389. unsigned int selector)
  390. {
  391. struct gpio_dev_priv *uc_priv;
  392. struct udevice *gpio_dev;
  393. unsigned int gpio_idx;
  394. static char pin_name[PINNAME_SIZE];
  395. /* look up for the bank which owns the requested pin */
  396. gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
  397. if (!gpio_dev) {
  398. snprintf(pin_name, PINNAME_SIZE, "Error");
  399. } else {
  400. uc_priv = dev_get_uclass_priv(gpio_dev);
  401. snprintf(pin_name, PINNAME_SIZE, "%s%d",
  402. uc_priv->bank_name,
  403. gpio_idx);
  404. }
  405. return pin_name;
  406. }
  407. static char *get_flags_string(ulong flags)
  408. {
  409. if (flags & GPIOD_OPEN_DRAIN)
  410. return "drive-open-drain";
  411. if (flags & GPIOD_OPEN_SOURCE)
  412. return "drive-open-source";
  413. if (flags & GPIOD_PULL_UP)
  414. return "bias-pull-up";
  415. if (flags & GPIOD_PULL_DOWN)
  416. return "bias-pull-down";
  417. return ".";
  418. }
  419. static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
  420. unsigned int selector,
  421. char *buf, int size)
  422. {
  423. struct udevice *gpio_dev;
  424. unsigned int gpio_idx;
  425. ulong flags;
  426. int function;
  427. /* look up for the bank which owns the requested pin */
  428. gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
  429. if (!gpio_dev) {
  430. snprintf(buf, size, "Error");
  431. } else {
  432. function = sb_gpio_get_function(gpio_dev, gpio_idx);
  433. flags = *get_gpio_flags(gpio_dev, gpio_idx);
  434. snprintf(buf, size, "gpio %s %s",
  435. function == GPIOF_OUTPUT ? "output" : "input",
  436. get_flags_string(flags));
  437. }
  438. return 0;
  439. }
  440. #if CONFIG_IS_ENABLED(ACPIGEN)
  441. static int sb_pinctrl_get_name(const struct udevice *dev, char *out_name)
  442. {
  443. return acpi_copy_name(out_name, "PINC");
  444. }
  445. #endif
  446. static int sandbox_pinctrl_probe(struct udevice *dev)
  447. {
  448. struct sb_pinctrl_priv *priv = dev_get_priv(dev);
  449. INIT_LIST_HEAD(&priv->gpio_dev);
  450. return 0;
  451. }
  452. static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
  453. .get_pin_name = sb_pinctrl_get_pin_name,
  454. .get_pins_count = sb_pinctrl_get_pins_count,
  455. .get_pin_muxing = sb_pinctrl_get_pin_muxing,
  456. };
  457. #if CONFIG_IS_ENABLED(ACPIGEN)
  458. struct acpi_ops pinctrl_sandbox_acpi_ops = {
  459. .get_name = sb_pinctrl_get_name,
  460. };
  461. #endif
  462. static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
  463. { .compatible = "sandbox,pinctrl-gpio" },
  464. { /* sentinel */ }
  465. };
  466. U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
  467. .name = "sandbox_pinctrl_gpio",
  468. .id = UCLASS_PINCTRL,
  469. .of_match = sandbox_pinctrl_gpio_match,
  470. .ops = &sandbox_pinctrl_gpio_ops,
  471. .bind = dm_scan_fdt_dev,
  472. .probe = sandbox_pinctrl_probe,
  473. .priv_auto = sizeof(struct sb_pinctrl_priv),
  474. ACPI_OPS_PTR(&pinctrl_sandbox_acpi_ops)
  475. };
  476. #endif /* PINCTRL */