smsc_sio1007.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
  4. */
  5. #include <common.h>
  6. #include <asm/io.h>
  7. #include <errno.h>
  8. #include <smsc_sio1007.h>
  9. static inline u8 sio1007_read(int port, int reg)
  10. {
  11. outb(reg, port);
  12. return inb(port + 1);
  13. }
  14. static inline void sio1007_write(int port, int reg, int val)
  15. {
  16. outb(reg, port);
  17. outb(val, port + 1);
  18. }
  19. static inline void sio1007_clrsetbits(int port, int reg, u8 clr, u8 set)
  20. {
  21. sio1007_write(port, reg, (sio1007_read(port, reg) & ~clr) | set);
  22. }
  23. void sio1007_enable_serial(int port, int num, int iobase, int irq)
  24. {
  25. if (num < 0 || num > SIO1007_UART_NUM)
  26. return;
  27. /* enter configuration state */
  28. outb(0x55, port);
  29. /* power on serial port and set up its i/o base & irq */
  30. if (!num) {
  31. sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART1_POWER_ON);
  32. sio1007_clrsetbits(port, UART1_IOBASE, 0xfe, iobase >> 2);
  33. sio1007_clrsetbits(port, UART_IRQ, 0xf0, irq << 4);
  34. } else {
  35. sio1007_clrsetbits(port, DEV_POWER_CTRL, 0, UART2_POWER_ON);
  36. sio1007_clrsetbits(port, UART2_IOBASE, 0xfe, iobase >> 2);
  37. sio1007_clrsetbits(port, UART_IRQ, 0x0f, irq);
  38. }
  39. /* exit configuration state */
  40. outb(0xaa, port);
  41. }
  42. void sio1007_enable_runtime(int port, int iobase)
  43. {
  44. /* enter configuration state */
  45. outb(0x55, port);
  46. /* set i/o base for the runtime register block */
  47. sio1007_clrsetbits(port, RTR_IOBASE_LOW, 0, iobase >> 4);
  48. sio1007_clrsetbits(port, RTR_IOBASE_HIGH, 0, iobase >> 12);
  49. /* turn on address decoding for this block */
  50. sio1007_clrsetbits(port, DEV_ACTIVATE, 0, RTR_EN);
  51. /* exit configuration state */
  52. outb(0xaa, port);
  53. }
  54. void sio1007_gpio_config(int port, int gpio, int dir, int pol, int type)
  55. {
  56. int reg = GPIO0_DIR;
  57. if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
  58. return;
  59. if (gpio >= GPIO_NUM_PER_GROUP) {
  60. reg = GPIO1_DIR;
  61. gpio -= GPIO_NUM_PER_GROUP;
  62. }
  63. /* enter configuration state */
  64. outb(0x55, port);
  65. /* set gpio pin direction, polority and type */
  66. sio1007_clrsetbits(port, reg, 1 << gpio, dir << gpio);
  67. sio1007_clrsetbits(port, reg + 1, 1 << gpio, pol << gpio);
  68. sio1007_clrsetbits(port, reg + 2, 1 << gpio, type << gpio);
  69. /* exit configuration state */
  70. outb(0xaa, port);
  71. }
  72. int sio1007_gpio_get_value(int port, int gpio)
  73. {
  74. int reg = GPIO0_DATA;
  75. int val;
  76. if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
  77. return -EINVAL;
  78. if (gpio >= GPIO_NUM_PER_GROUP) {
  79. reg = GPIO1_DATA;
  80. gpio -= GPIO_NUM_PER_GROUP;
  81. }
  82. val = inb(port + reg);
  83. if (val & (1 << gpio))
  84. return 1;
  85. else
  86. return 0;
  87. }
  88. void sio1007_gpio_set_value(int port, int gpio, int val)
  89. {
  90. int reg = GPIO0_DATA;
  91. u8 data;
  92. if (gpio < 0 || gpio > SIO1007_GPIO_NUM)
  93. return;
  94. if (gpio >= GPIO_NUM_PER_GROUP) {
  95. reg = GPIO1_DATA;
  96. gpio -= GPIO_NUM_PER_GROUP;
  97. }
  98. data = inb(port + reg);
  99. data &= ~(1 << gpio);
  100. data |= (val << gpio);
  101. outb(data, port + reg);
  102. }