1 // SPDX-License-Identifier: GPL-2.0+
3 * HD44780 Character LCD driver for Linux
5 * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
6 * Copyright (C) 2016-2017 Glider bvba
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/module.h>
12 #include <linux/mod_devicetable.h>
13 #include <linux/platform_device.h>
14 #include <linux/property.h>
15 #include <linux/slab.h>
18 #include "hd44780_common.h"
21 /* Order does matter due to writing to GPIO array subsets! */
22 PIN_DATA0
, /* Optional */
23 PIN_DATA1
, /* Optional */
24 PIN_DATA2
, /* Optional */
25 PIN_DATA3
, /* Optional */
31 PIN_CTRL_RW
, /* Optional */
33 PIN_CTRL_BL
, /* Optional */
38 struct gpio_desc
*pins
[PIN_NUM
];
41 static void hd44780_backlight(struct charlcd
*lcd
, enum charlcd_onoff on
)
43 struct hd44780_common
*hdc
= lcd
->drvdata
;
44 struct hd44780
*hd
= hdc
->hd44780
;
46 if (hd
->pins
[PIN_CTRL_BL
])
47 gpiod_set_value_cansleep(hd
->pins
[PIN_CTRL_BL
], on
);
50 static void hd44780_strobe_gpio(struct hd44780
*hd
)
52 /* Maintain the data during 20 us before the strobe */
55 gpiod_set_value_cansleep(hd
->pins
[PIN_CTRL_E
], 1);
57 /* Maintain the strobe during 40 us */
60 gpiod_set_value_cansleep(hd
->pins
[PIN_CTRL_E
], 0);
63 /* write to an LCD panel register in 8 bit GPIO mode */
64 static void hd44780_write_gpio8(struct hd44780
*hd
, u8 val
, unsigned int rs
)
66 DECLARE_BITMAP(values
, 10); /* for DATA[0-7], RS, RW */
70 __assign_bit(8, values
, rs
);
71 n
= hd
->pins
[PIN_CTRL_RW
] ? 10 : 9;
73 /* Present the data to the port */
74 gpiod_set_array_value_cansleep(n
, &hd
->pins
[PIN_DATA0
], NULL
, values
);
76 hd44780_strobe_gpio(hd
);
79 /* write to an LCD panel register in 4 bit GPIO mode */
80 static void hd44780_write_gpio4(struct hd44780
*hd
, u8 val
, unsigned int rs
)
82 DECLARE_BITMAP(values
, 6); /* for DATA[4-7], RS, RW */
85 /* High nibble + RS, RW */
87 __assign_bit(4, values
, rs
);
88 n
= hd
->pins
[PIN_CTRL_RW
] ? 6 : 5;
90 /* Present the data to the port */
91 gpiod_set_array_value_cansleep(n
, &hd
->pins
[PIN_DATA4
], NULL
, values
);
93 hd44780_strobe_gpio(hd
);
97 values
[0] |= val
& 0x0f;
99 /* Present the data to the port */
100 gpiod_set_array_value_cansleep(n
, &hd
->pins
[PIN_DATA4
], NULL
, values
);
102 hd44780_strobe_gpio(hd
);
105 /* Send a command to the LCD panel in 8 bit GPIO mode */
106 static void hd44780_write_cmd_gpio8(struct hd44780_common
*hdc
, int cmd
)
108 struct hd44780
*hd
= hdc
->hd44780
;
110 hd44780_write_gpio8(hd
, cmd
, 0);
112 /* The shortest command takes at least 120 us */
116 /* Send data to the LCD panel in 8 bit GPIO mode */
117 static void hd44780_write_data_gpio8(struct hd44780_common
*hdc
, int data
)
119 struct hd44780
*hd
= hdc
->hd44780
;
121 hd44780_write_gpio8(hd
, data
, 1);
123 /* The shortest data takes at least 45 us */
127 static const struct charlcd_ops hd44780_ops_gpio8
= {
128 .backlight
= hd44780_backlight
,
129 .print
= hd44780_common_print
,
130 .gotoxy
= hd44780_common_gotoxy
,
131 .home
= hd44780_common_home
,
132 .clear_display
= hd44780_common_clear_display
,
133 .init_display
= hd44780_common_init_display
,
134 .shift_cursor
= hd44780_common_shift_cursor
,
135 .shift_display
= hd44780_common_shift_display
,
136 .display
= hd44780_common_display
,
137 .cursor
= hd44780_common_cursor
,
138 .blink
= hd44780_common_blink
,
139 .fontsize
= hd44780_common_fontsize
,
140 .lines
= hd44780_common_lines
,
141 .redefine_char
= hd44780_common_redefine_char
,
144 /* Send a command to the LCD panel in 4 bit GPIO mode */
145 static void hd44780_write_cmd_gpio4(struct hd44780_common
*hdc
, int cmd
)
147 struct hd44780
*hd
= hdc
->hd44780
;
149 hd44780_write_gpio4(hd
, cmd
, 0);
151 /* The shortest command takes at least 120 us */
155 /* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */
156 static void hd44780_write_cmd_raw_gpio4(struct hd44780_common
*hdc
, int cmd
)
158 DECLARE_BITMAP(values
, 6); /* for DATA[4-7], RS, RW */
159 struct hd44780
*hd
= hdc
->hd44780
;
162 /* Command nibble + RS, RW */
163 values
[0] = cmd
& 0x0f;
164 n
= hd
->pins
[PIN_CTRL_RW
] ? 6 : 5;
166 /* Present the data to the port */
167 gpiod_set_array_value_cansleep(n
, &hd
->pins
[PIN_DATA4
], NULL
, values
);
169 hd44780_strobe_gpio(hd
);
172 /* Send data to the LCD panel in 4 bit GPIO mode */
173 static void hd44780_write_data_gpio4(struct hd44780_common
*hdc
, int data
)
175 struct hd44780
*hd
= hdc
->hd44780
;
177 hd44780_write_gpio4(hd
, data
, 1);
179 /* The shortest data takes at least 45 us */
183 static const struct charlcd_ops hd44780_ops_gpio4
= {
184 .backlight
= hd44780_backlight
,
185 .print
= hd44780_common_print
,
186 .gotoxy
= hd44780_common_gotoxy
,
187 .home
= hd44780_common_home
,
188 .clear_display
= hd44780_common_clear_display
,
189 .init_display
= hd44780_common_init_display
,
190 .shift_cursor
= hd44780_common_shift_cursor
,
191 .shift_display
= hd44780_common_shift_display
,
192 .display
= hd44780_common_display
,
193 .cursor
= hd44780_common_cursor
,
194 .blink
= hd44780_common_blink
,
195 .fontsize
= hd44780_common_fontsize
,
196 .lines
= hd44780_common_lines
,
197 .redefine_char
= hd44780_common_redefine_char
,
200 static int hd44780_probe(struct platform_device
*pdev
)
202 struct device
*dev
= &pdev
->dev
;
203 unsigned int i
, base
;
205 struct hd44780_common
*hdc
;
207 int ifwidth
, ret
= -ENOMEM
;
210 ifwidth
= gpiod_count(dev
, "data");
225 hdc
= hd44780_common_alloc();
229 lcd
= charlcd_alloc();
233 hd
= kzalloc(sizeof(struct hd44780
), GFP_KERNEL
);
239 for (i
= 0; i
< ifwidth
; i
++) {
240 hd
->pins
[base
+ i
] = devm_gpiod_get_index(dev
, "data", i
,
242 if (IS_ERR(hd
->pins
[base
+ i
])) {
243 ret
= PTR_ERR(hd
->pins
[base
+ i
]);
248 hd
->pins
[PIN_CTRL_E
] = devm_gpiod_get(dev
, "enable", GPIOD_OUT_LOW
);
249 if (IS_ERR(hd
->pins
[PIN_CTRL_E
])) {
250 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_E
]);
254 hd
->pins
[PIN_CTRL_RS
] = devm_gpiod_get(dev
, "rs", GPIOD_OUT_HIGH
);
255 if (IS_ERR(hd
->pins
[PIN_CTRL_RS
])) {
256 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_RS
]);
261 hd
->pins
[PIN_CTRL_RW
] = devm_gpiod_get_optional(dev
, "rw",
263 if (IS_ERR(hd
->pins
[PIN_CTRL_RW
])) {
264 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_RW
]);
268 hd
->pins
[PIN_CTRL_BL
] = devm_gpiod_get_optional(dev
, "backlight",
270 if (IS_ERR(hd
->pins
[PIN_CTRL_BL
])) {
271 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_BL
]);
275 /* Required properties */
276 ret
= device_property_read_u32(dev
, "display-height-chars",
280 ret
= device_property_read_u32(dev
, "display-width-chars", &lcd
->width
);
285 * On displays with more than two rows, the internal buffer width is
286 * usually equal to the display width
289 hdc
->bwidth
= lcd
->width
;
291 /* Optional properties */
292 device_property_read_u32(dev
, "internal-buffer-width", &hdc
->bwidth
);
294 hdc
->ifwidth
= ifwidth
;
296 lcd
->ops
= &hd44780_ops_gpio8
;
297 hdc
->write_data
= hd44780_write_data_gpio8
;
298 hdc
->write_cmd
= hd44780_write_cmd_gpio8
;
300 lcd
->ops
= &hd44780_ops_gpio4
;
301 hdc
->write_data
= hd44780_write_data_gpio4
;
302 hdc
->write_cmd
= hd44780_write_cmd_gpio4
;
303 hdc
->write_cmd_raw4
= hd44780_write_cmd_raw_gpio4
;
306 ret
= charlcd_register(lcd
);
310 platform_set_drvdata(pdev
, lcd
);
322 static int hd44780_remove(struct platform_device
*pdev
)
324 struct charlcd
*lcd
= platform_get_drvdata(pdev
);
327 charlcd_unregister(lcd
);
333 static const struct of_device_id hd44780_of_match
[] = {
334 { .compatible
= "hit,hd44780" },
337 MODULE_DEVICE_TABLE(of
, hd44780_of_match
);
339 static struct platform_driver hd44780_driver
= {
340 .probe
= hd44780_probe
,
341 .remove
= hd44780_remove
,
344 .of_match_table
= hd44780_of_match
,
348 module_platform_driver(hd44780_driver
);
349 MODULE_DESCRIPTION("HD44780 Character LCD driver");
350 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
351 MODULE_LICENSE("GPL");