diff options
author | Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com> | 2015-01-21 05:32:21 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-01-29 07:46:29 -0500 |
commit | 920dfd824789b4058e91d26e2c6dd01a00ab28ec (patch) | |
tree | 238a4284152f85fae62b79463d6f4c0eb1d59da8 /drivers/gpio/gpio-sch.c | |
parent | 68d77d5168bdb922e0f100d0ee5e5e78aa0989af (diff) |
gpio: sch: Consolidate similar algorithms
Consolidating similar algorithms into common functions to make
GPIO SCH simpler and manageable.
Signed-off-by: Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-sch.c')
-rw-r--r-- | drivers/gpio/gpio-sch.c | 83 |
1 files changed, 29 insertions, 54 deletions
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 0271022a66f6..b72906f5b999 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c | |||
@@ -41,7 +41,7 @@ struct sch_gpio { | |||
41 | unsigned short resume_base; | 41 | unsigned short resume_base; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | #define to_sch_gpio(c) container_of(c, struct sch_gpio, chip) | 44 | #define to_sch_gpio(gc) container_of(gc, struct sch_gpio, chip) |
45 | 45 | ||
46 | static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio, | 46 | static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio, |
47 | unsigned reg) | 47 | unsigned reg) |
@@ -63,75 +63,59 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio) | |||
63 | return gpio % 8; | 63 | return gpio % 8; |
64 | } | 64 | } |
65 | 65 | ||
66 | static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio) | 66 | static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg) |
67 | { | 67 | { |
68 | struct sch_gpio *sch = to_sch_gpio(gc); | ||
68 | unsigned short offset, bit; | 69 | unsigned short offset, bit; |
69 | u8 enable; | 70 | u8 reg_val; |
70 | |||
71 | spin_lock(&sch->lock); | ||
72 | 71 | ||
73 | offset = sch_gpio_offset(sch, gpio, GEN); | 72 | offset = sch_gpio_offset(sch, gpio, reg); |
74 | bit = sch_gpio_bit(sch, gpio); | 73 | bit = sch_gpio_bit(sch, gpio); |
75 | 74 | ||
76 | enable = inb(sch->iobase + offset); | 75 | reg_val = !!(inb(sch->iobase + offset) & BIT(bit)); |
77 | if (!(enable & (1 << bit))) | ||
78 | outb(enable | (1 << bit), sch->iobase + offset); | ||
79 | 76 | ||
80 | spin_unlock(&sch->lock); | 77 | return reg_val; |
81 | } | 78 | } |
82 | 79 | ||
83 | static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) | 80 | static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg, |
81 | int val) | ||
84 | { | 82 | { |
85 | struct sch_gpio *sch = to_sch_gpio(gc); | 83 | struct sch_gpio *sch = to_sch_gpio(gc); |
86 | u8 curr_dirs; | ||
87 | unsigned short offset, bit; | 84 | unsigned short offset, bit; |
85 | u8 reg_val; | ||
88 | 86 | ||
89 | spin_lock(&sch->lock); | 87 | offset = sch_gpio_offset(sch, gpio, reg); |
88 | bit = sch_gpio_bit(sch, gpio); | ||
90 | 89 | ||
91 | offset = sch_gpio_offset(sch, gpio_num, GIO); | 90 | reg_val = inb(sch->iobase + offset); |
92 | bit = sch_gpio_bit(sch, gpio_num); | ||
93 | 91 | ||
94 | curr_dirs = inb(sch->iobase + offset); | 92 | if (val) |
93 | outb(reg_val | BIT(bit), sch->iobase + offset); | ||
94 | else | ||
95 | outb((reg_val & ~BIT(bit)), sch->iobase + offset); | ||
96 | } | ||
95 | 97 | ||
96 | if (!(curr_dirs & (1 << bit))) | 98 | static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) |
97 | outb(curr_dirs | (1 << bit), sch->iobase + offset); | 99 | { |
100 | struct sch_gpio *sch = to_sch_gpio(gc); | ||
98 | 101 | ||
102 | spin_lock(&sch->lock); | ||
103 | sch_gpio_reg_set(gc, gpio_num, GIO, 1); | ||
99 | spin_unlock(&sch->lock); | 104 | spin_unlock(&sch->lock); |
100 | return 0; | 105 | return 0; |
101 | } | 106 | } |
102 | 107 | ||
103 | static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num) | 108 | static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num) |
104 | { | 109 | { |
105 | struct sch_gpio *sch = to_sch_gpio(gc); | 110 | return sch_gpio_reg_get(gc, gpio_num, GLV); |
106 | int res; | ||
107 | unsigned short offset, bit; | ||
108 | |||
109 | offset = sch_gpio_offset(sch, gpio_num, GLV); | ||
110 | bit = sch_gpio_bit(sch, gpio_num); | ||
111 | |||
112 | res = !!(inb(sch->iobase + offset) & (1 << bit)); | ||
113 | |||
114 | return res; | ||
115 | } | 111 | } |
116 | 112 | ||
117 | static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val) | 113 | static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val) |
118 | { | 114 | { |
119 | struct sch_gpio *sch = to_sch_gpio(gc); | 115 | struct sch_gpio *sch = to_sch_gpio(gc); |
120 | u8 curr_vals; | ||
121 | unsigned short offset, bit; | ||
122 | 116 | ||
123 | spin_lock(&sch->lock); | 117 | spin_lock(&sch->lock); |
124 | 118 | sch_gpio_reg_set(gc, gpio_num, GLV, val); | |
125 | offset = sch_gpio_offset(sch, gpio_num, GLV); | ||
126 | bit = sch_gpio_bit(sch, gpio_num); | ||
127 | |||
128 | curr_vals = inb(sch->iobase + offset); | ||
129 | |||
130 | if (val) | ||
131 | outb(curr_vals | (1 << bit), sch->iobase + offset); | ||
132 | else | ||
133 | outb((curr_vals & ~(1 << bit)), sch->iobase + offset); | ||
134 | |||
135 | spin_unlock(&sch->lock); | 119 | spin_unlock(&sch->lock); |
136 | } | 120 | } |
137 | 121 | ||
@@ -139,18 +123,9 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num, | |||
139 | int val) | 123 | int val) |
140 | { | 124 | { |
141 | struct sch_gpio *sch = to_sch_gpio(gc); | 125 | struct sch_gpio *sch = to_sch_gpio(gc); |
142 | u8 curr_dirs; | ||
143 | unsigned short offset, bit; | ||
144 | 126 | ||
145 | spin_lock(&sch->lock); | 127 | spin_lock(&sch->lock); |
146 | 128 | sch_gpio_reg_set(gc, gpio_num, GIO, 0); | |
147 | offset = sch_gpio_offset(sch, gpio_num, GIO); | ||
148 | bit = sch_gpio_bit(sch, gpio_num); | ||
149 | |||
150 | curr_dirs = inb(sch->iobase + offset); | ||
151 | if (curr_dirs & (1 << bit)) | ||
152 | outb(curr_dirs & ~(1 << bit), sch->iobase + offset); | ||
153 | |||
154 | spin_unlock(&sch->lock); | 129 | spin_unlock(&sch->lock); |
155 | 130 | ||
156 | /* | 131 | /* |
@@ -209,13 +184,13 @@ static int sch_gpio_probe(struct platform_device *pdev) | |||
209 | * GPIO7 is configured by the CMC as SLPIOVR | 184 | * GPIO7 is configured by the CMC as SLPIOVR |
210 | * Enable GPIO[9:8] core powered gpios explicitly | 185 | * Enable GPIO[9:8] core powered gpios explicitly |
211 | */ | 186 | */ |
212 | sch_gpio_enable(sch, 8); | 187 | sch_gpio_reg_set(&sch->chip, 8, GEN, 1); |
213 | sch_gpio_enable(sch, 9); | 188 | sch_gpio_reg_set(&sch->chip, 9, GEN, 1); |
214 | /* | 189 | /* |
215 | * SUS_GPIO[2:0] enabled by default | 190 | * SUS_GPIO[2:0] enabled by default |
216 | * Enable SUS_GPIO3 resume powered gpio explicitly | 191 | * Enable SUS_GPIO3 resume powered gpio explicitly |
217 | */ | 192 | */ |
218 | sch_gpio_enable(sch, 13); | 193 | sch_gpio_reg_set(&sch->chip, 13, GEN, 1); |
219 | break; | 194 | break; |
220 | 195 | ||
221 | case PCI_DEVICE_ID_INTEL_ITC_LPC: | 196 | case PCI_DEVICE_ID_INTEL_ITC_LPC: |