mpc83xx_spisel_boot.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2019 DEIF A/S
  4. *
  5. * GPIO driver to set/clear SPISEL_BOOT pin on mpc83xx.
  6. */
  7. #include <common.h>
  8. #include <log.h>
  9. #include <dm.h>
  10. #include <mapmem.h>
  11. #include <asm/gpio.h>
  12. struct mpc83xx_spisel_boot {
  13. u32 __iomem *spi_cs;
  14. ulong addr;
  15. uint gpio_count;
  16. ulong type;
  17. };
  18. static u32 gpio_mask(uint gpio)
  19. {
  20. return (1U << (31 - (gpio)));
  21. }
  22. static int mpc83xx_spisel_boot_direction_input(struct udevice *dev, uint gpio)
  23. {
  24. return -EINVAL;
  25. }
  26. static int mpc83xx_spisel_boot_set_value(struct udevice *dev, uint gpio, int value)
  27. {
  28. struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
  29. debug("%s: gpio=%d, value=%u, gpio_mask=0x%08x\n", __func__,
  30. gpio, value, gpio_mask(gpio));
  31. if (value)
  32. setbits_be32(data->spi_cs, gpio_mask(gpio));
  33. else
  34. clrbits_be32(data->spi_cs, gpio_mask(gpio));
  35. return 0;
  36. }
  37. static int mpc83xx_spisel_boot_direction_output(struct udevice *dev, uint gpio, int value)
  38. {
  39. return 0;
  40. }
  41. static int mpc83xx_spisel_boot_get_value(struct udevice *dev, uint gpio)
  42. {
  43. struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
  44. return !!(in_be32(data->spi_cs) & gpio_mask(gpio));
  45. }
  46. static int mpc83xx_spisel_boot_get_function(struct udevice *dev, uint gpio)
  47. {
  48. return GPIOF_OUTPUT;
  49. }
  50. #if CONFIG_IS_ENABLED(OF_CONTROL)
  51. static int mpc83xx_spisel_boot_ofdata_to_platdata(struct udevice *dev)
  52. {
  53. struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
  54. fdt_addr_t addr;
  55. u32 reg[2];
  56. dev_read_u32_array(dev, "reg", reg, 2);
  57. addr = dev_translate_address(dev, reg);
  58. plat->addr = addr;
  59. plat->size = reg[1];
  60. plat->ngpios = dev_read_u32_default(dev, "ngpios", 1);
  61. return 0;
  62. }
  63. #endif
  64. static int mpc83xx_spisel_boot_platdata_to_priv(struct udevice *dev)
  65. {
  66. struct mpc83xx_spisel_boot *priv = dev_get_priv(dev);
  67. struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev);
  68. unsigned long size = plat->size;
  69. ulong driver_data = dev_get_driver_data(dev);
  70. if (size == 0)
  71. size = 0x04;
  72. priv->addr = plat->addr;
  73. priv->spi_cs = map_sysmem(plat->addr, size);
  74. if (!priv->spi_cs)
  75. return -ENOMEM;
  76. priv->gpio_count = plat->ngpios;
  77. priv->type = driver_data;
  78. return 0;
  79. }
  80. static int mpc83xx_spisel_boot_probe(struct udevice *dev)
  81. {
  82. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  83. struct mpc83xx_spisel_boot *data = dev_get_priv(dev);
  84. char name[32], *str;
  85. mpc83xx_spisel_boot_platdata_to_priv(dev);
  86. snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
  87. str = strdup(name);
  88. if (!str)
  89. return -ENOMEM;
  90. uc_priv->bank_name = str;
  91. uc_priv->gpio_count = data->gpio_count;
  92. return 0;
  93. }
  94. static const struct dm_gpio_ops mpc83xx_spisel_boot_ops = {
  95. .direction_input = mpc83xx_spisel_boot_direction_input,
  96. .direction_output = mpc83xx_spisel_boot_direction_output,
  97. .get_value = mpc83xx_spisel_boot_get_value,
  98. .set_value = mpc83xx_spisel_boot_set_value,
  99. .get_function = mpc83xx_spisel_boot_get_function,
  100. };
  101. static const struct udevice_id mpc83xx_spisel_boot_ids[] = {
  102. { .compatible = "fsl,mpc8309-spisel-boot" },
  103. { .compatible = "fsl,mpc83xx-spisel-boot" },
  104. { /* sentinel */ }
  105. };
  106. U_BOOT_DRIVER(spisel_boot_mpc83xx) = {
  107. .name = "spisel_boot_mpc83xx",
  108. .id = UCLASS_GPIO,
  109. .ops = &mpc83xx_spisel_boot_ops,
  110. #if CONFIG_IS_ENABLED(OF_CONTROL)
  111. .ofdata_to_platdata = mpc83xx_spisel_boot_ofdata_to_platdata,
  112. .platdata_auto_alloc_size = sizeof(struct mpc8xxx_gpio_plat),
  113. .of_match = mpc83xx_spisel_boot_ids,
  114. #endif
  115. .probe = mpc83xx_spisel_boot_probe,
  116. .priv_auto_alloc_size = sizeof(struct mpc83xx_spisel_boot),
  117. };