1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * HD44780 Character LCD driver for Linux
4 *
5 * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
6 * Copyright (C) 2016-2017 Glider bvba
7 */
8
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/property.h>
14 #include <linux/slab.h>
15
16 #include "charlcd.h"
17 #include "hd44780_common.h"
18
19 enum hd44780_pin {
20 /* Order does matter due to writing to GPIO array subsets! */
21 PIN_DATA0, /* Optional */
22 PIN_DATA1, /* Optional */
23 PIN_DATA2, /* Optional */
24 PIN_DATA3, /* Optional */
25 PIN_DATA4,
26 PIN_DATA5,
27 PIN_DATA6,
28 PIN_DATA7,
29 PIN_CTRL_RS,
30 PIN_CTRL_RW, /* Optional */
31 PIN_CTRL_E,
32 PIN_CTRL_BL, /* Optional */
33 PIN_NUM
34 };
35
36 struct hd44780 {
37 struct gpio_desc *pins[PIN_NUM];
38 };
39
hd44780_backlight(struct charlcd * lcd,enum charlcd_onoff on)40 static void hd44780_backlight(struct charlcd *lcd, enum charlcd_onoff on)
41 {
42 struct hd44780_common *hdc = lcd->drvdata;
43 struct hd44780 *hd = hdc->hd44780;
44
45 if (hd->pins[PIN_CTRL_BL])
46 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_BL], on);
47 }
48
hd44780_strobe_gpio(struct hd44780 * hd)49 static void hd44780_strobe_gpio(struct hd44780 *hd)
50 {
51 /* Maintain the data during 20 us before the strobe */
52 udelay(20);
53
54 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 1);
55
56 /* Maintain the strobe during 40 us */
57 udelay(40);
58
59 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 0);
60 }
61
62 /* write to an LCD panel register in 8 bit GPIO mode */
hd44780_write_gpio8(struct hd44780 * hd,u8 val,unsigned int rs)63 static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs)
64 {
65 DECLARE_BITMAP(values, 10); /* for DATA[0-7], RS, RW */
66 unsigned int n;
67
68 values[0] = val;
69 __assign_bit(8, values, rs);
70 n = hd->pins[PIN_CTRL_RW] ? 10 : 9;
71
72 /* Present the data to the port */
73 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], NULL, values);
74
75 hd44780_strobe_gpio(hd);
76 }
77
78 /* write to an LCD panel register in 4 bit GPIO mode */
hd44780_write_gpio4(struct hd44780 * hd,u8 val,unsigned int rs)79 static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs)
80 {
81 DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */
82 unsigned int n;
83
84 /* High nibble + RS, RW */
85 values[0] = val >> 4;
86 __assign_bit(4, values, rs);
87 n = hd->pins[PIN_CTRL_RW] ? 6 : 5;
88
89 /* Present the data to the port */
90 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values);
91
92 hd44780_strobe_gpio(hd);
93
94 /* Low nibble */
95 values[0] &= ~0x0fUL;
96 values[0] |= val & 0x0f;
97
98 /* Present the data to the port */
99 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values);
100
101 hd44780_strobe_gpio(hd);
102 }
103
104 /* Send a command to the LCD panel in 8 bit GPIO mode */
hd44780_write_cmd_gpio8(struct hd44780_common * hdc,int cmd)105 static void hd44780_write_cmd_gpio8(struct hd44780_common *hdc, int cmd)
106 {
107 struct hd44780 *hd = hdc->hd44780;
108
109 hd44780_write_gpio8(hd, cmd, 0);
110
111 /* The shortest command takes at least 120 us */
112 udelay(120);
113 }
114
115 /* Send data to the LCD panel in 8 bit GPIO mode */
hd44780_write_data_gpio8(struct hd44780_common * hdc,int data)116 static void hd44780_write_data_gpio8(struct hd44780_common *hdc, int data)
117 {
118 struct hd44780 *hd = hdc->hd44780;
119
120 hd44780_write_gpio8(hd, data, 1);
121
122 /* The shortest data takes at least 45 us */
123 udelay(45);
124 }
125
126 static const struct charlcd_ops hd44780_ops_gpio8 = {
127 .backlight = hd44780_backlight,
128 .print = hd44780_common_print,
129 .gotoxy = hd44780_common_gotoxy,
130 .home = hd44780_common_home,
131 .clear_display = hd44780_common_clear_display,
132 .init_display = hd44780_common_init_display,
133 .shift_cursor = hd44780_common_shift_cursor,
134 .shift_display = hd44780_common_shift_display,
135 .display = hd44780_common_display,
136 .cursor = hd44780_common_cursor,
137 .blink = hd44780_common_blink,
138 .fontsize = hd44780_common_fontsize,
139 .lines = hd44780_common_lines,
140 .redefine_char = hd44780_common_redefine_char,
141 };
142
143 /* Send a command to the LCD panel in 4 bit GPIO mode */
hd44780_write_cmd_gpio4(struct hd44780_common * hdc,int cmd)144 static void hd44780_write_cmd_gpio4(struct hd44780_common *hdc, int cmd)
145 {
146 struct hd44780 *hd = hdc->hd44780;
147
148 hd44780_write_gpio4(hd, cmd, 0);
149
150 /* The shortest command takes at least 120 us */
151 udelay(120);
152 }
153
154 /* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */
hd44780_write_cmd_raw_gpio4(struct hd44780_common * hdc,int cmd)155 static void hd44780_write_cmd_raw_gpio4(struct hd44780_common *hdc, int cmd)
156 {
157 DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */
158 struct hd44780 *hd = hdc->hd44780;
159 unsigned int n;
160
161 /* Command nibble + RS, RW */
162 values[0] = cmd & 0x0f;
163 n = hd->pins[PIN_CTRL_RW] ? 6 : 5;
164
165 /* Present the data to the port */
166 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values);
167
168 hd44780_strobe_gpio(hd);
169 }
170
171 /* Send data to the LCD panel in 4 bit GPIO mode */
hd44780_write_data_gpio4(struct hd44780_common * hdc,int data)172 static void hd44780_write_data_gpio4(struct hd44780_common *hdc, int data)
173 {
174 struct hd44780 *hd = hdc->hd44780;
175
176 hd44780_write_gpio4(hd, data, 1);
177
178 /* The shortest data takes at least 45 us */
179 udelay(45);
180 }
181
182 static const struct charlcd_ops hd44780_ops_gpio4 = {
183 .backlight = hd44780_backlight,
184 .print = hd44780_common_print,
185 .gotoxy = hd44780_common_gotoxy,
186 .home = hd44780_common_home,
187 .clear_display = hd44780_common_clear_display,
188 .init_display = hd44780_common_init_display,
189 .shift_cursor = hd44780_common_shift_cursor,
190 .shift_display = hd44780_common_shift_display,
191 .display = hd44780_common_display,
192 .cursor = hd44780_common_cursor,
193 .blink = hd44780_common_blink,
194 .fontsize = hd44780_common_fontsize,
195 .lines = hd44780_common_lines,
196 .redefine_char = hd44780_common_redefine_char,
197 };
198
hd44780_probe(struct platform_device * pdev)199 static int hd44780_probe(struct platform_device *pdev)
200 {
201 struct device *dev = &pdev->dev;
202 unsigned int i, base;
203 struct charlcd *lcd;
204 struct hd44780_common *hdc;
205 struct hd44780 *hd;
206 int ifwidth, ret = -ENOMEM;
207
208 /* Required pins */
209 ifwidth = gpiod_count(dev, "data");
210 if (ifwidth < 0)
211 return ifwidth;
212
213 switch (ifwidth) {
214 case 4:
215 base = PIN_DATA4;
216 break;
217 case 8:
218 base = PIN_DATA0;
219 break;
220 default:
221 return -EINVAL;
222 }
223
224 lcd = hd44780_common_alloc();
225 if (!lcd)
226 return -ENOMEM;
227
228 hd = kzalloc_obj(*hd);
229 if (!hd)
230 goto fail2;
231
232 hdc = lcd->drvdata;
233 hdc->hd44780 = hd;
234
235 for (i = 0; i < ifwidth; i++) {
236 hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i,
237 GPIOD_OUT_LOW);
238 if (IS_ERR(hd->pins[base + i])) {
239 ret = PTR_ERR(hd->pins[base + i]);
240 goto fail3;
241 }
242 }
243
244 hd->pins[PIN_CTRL_E] = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
245 if (IS_ERR(hd->pins[PIN_CTRL_E])) {
246 ret = PTR_ERR(hd->pins[PIN_CTRL_E]);
247 goto fail3;
248 }
249
250 hd->pins[PIN_CTRL_RS] = devm_gpiod_get(dev, "rs", GPIOD_OUT_HIGH);
251 if (IS_ERR(hd->pins[PIN_CTRL_RS])) {
252 ret = PTR_ERR(hd->pins[PIN_CTRL_RS]);
253 goto fail3;
254 }
255
256 /* Optional pins */
257 hd->pins[PIN_CTRL_RW] = devm_gpiod_get_optional(dev, "rw",
258 GPIOD_OUT_LOW);
259 if (IS_ERR(hd->pins[PIN_CTRL_RW])) {
260 ret = PTR_ERR(hd->pins[PIN_CTRL_RW]);
261 goto fail3;
262 }
263
264 hd->pins[PIN_CTRL_BL] = devm_gpiod_get_optional(dev, "backlight",
265 GPIOD_OUT_LOW);
266 if (IS_ERR(hd->pins[PIN_CTRL_BL])) {
267 ret = PTR_ERR(hd->pins[PIN_CTRL_BL]);
268 goto fail3;
269 }
270
271 /* Required properties */
272 ret = device_property_read_u32(dev, "display-height-chars",
273 &lcd->height);
274 if (ret)
275 goto fail3;
276 ret = device_property_read_u32(dev, "display-width-chars", &lcd->width);
277 if (ret)
278 goto fail3;
279
280 /*
281 * On displays with more than two rows, the internal buffer width is
282 * usually equal to the display width
283 */
284 if (lcd->height > 2)
285 hdc->bwidth = lcd->width;
286
287 /* Optional properties */
288 device_property_read_u32(dev, "internal-buffer-width", &hdc->bwidth);
289
290 hdc->ifwidth = ifwidth;
291 if (ifwidth == 8) {
292 lcd->ops = &hd44780_ops_gpio8;
293 hdc->write_data = hd44780_write_data_gpio8;
294 hdc->write_cmd = hd44780_write_cmd_gpio8;
295 } else {
296 lcd->ops = &hd44780_ops_gpio4;
297 hdc->write_data = hd44780_write_data_gpio4;
298 hdc->write_cmd = hd44780_write_cmd_gpio4;
299 hdc->write_cmd_raw4 = hd44780_write_cmd_raw_gpio4;
300 }
301
302 ret = charlcd_register(lcd);
303 if (ret)
304 goto fail3;
305
306 platform_set_drvdata(pdev, lcd);
307 return 0;
308
309 fail3:
310 kfree(hd);
311 fail2:
312 hd44780_common_free(lcd);
313 return ret;
314 }
315
hd44780_remove(struct platform_device * pdev)316 static void hd44780_remove(struct platform_device *pdev)
317 {
318 struct charlcd *lcd = platform_get_drvdata(pdev);
319 struct hd44780_common *hdc = lcd->drvdata;
320
321 charlcd_unregister(lcd);
322 kfree(hdc->hd44780);
323 hd44780_common_free(lcd);
324 }
325
326 static const struct of_device_id hd44780_of_match[] = {
327 { .compatible = "hit,hd44780" },
328 { /* sentinel */ }
329 };
330 MODULE_DEVICE_TABLE(of, hd44780_of_match);
331
332 static struct platform_driver hd44780_driver = {
333 .probe = hd44780_probe,
334 .remove = hd44780_remove,
335 .driver = {
336 .name = "hd44780",
337 .of_match_table = hd44780_of_match,
338 },
339 };
340
341 module_platform_driver(hd44780_driver);
342 MODULE_DESCRIPTION("HD44780 Character LCD driver");
343 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
344 MODULE_LICENSE("GPL");
345