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
,
136 /* Send a command to the LCD panel in 4 bit GPIO mode */
137 static void hd44780_write_cmd_gpio4(struct hd44780_common
*hdc
, int cmd
)
139 struct hd44780
*hd
= hdc
->hd44780
;
141 hd44780_write_gpio4(hd
, cmd
, 0);
143 /* The shortest command takes at least 120 us */
147 /* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */
148 static void hd44780_write_cmd_raw_gpio4(struct hd44780_common
*hdc
, int cmd
)
150 DECLARE_BITMAP(values
, 6); /* for DATA[4-7], RS, RW */
151 struct hd44780
*hd
= hdc
->hd44780
;
154 /* Command nibble + RS, RW */
155 values
[0] = cmd
& 0x0f;
156 n
= hd
->pins
[PIN_CTRL_RW
] ? 6 : 5;
158 /* Present the data to the port */
159 gpiod_set_array_value_cansleep(n
, &hd
->pins
[PIN_DATA4
], NULL
, values
);
161 hd44780_strobe_gpio(hd
);
164 /* Send data to the LCD panel in 4 bit GPIO mode */
165 static void hd44780_write_data_gpio4(struct hd44780_common
*hdc
, int data
)
167 struct hd44780
*hd
= hdc
->hd44780
;
169 hd44780_write_gpio4(hd
, data
, 1);
171 /* The shortest data takes at least 45 us */
175 static const struct charlcd_ops hd44780_ops_gpio4
= {
176 .backlight
= hd44780_backlight
,
177 .print
= hd44780_common_print
,
178 .gotoxy
= hd44780_common_gotoxy
,
179 .home
= hd44780_common_home
,
180 .clear_display
= hd44780_common_clear_display
,
181 .init_display
= hd44780_common_init_display
,
184 static int hd44780_probe(struct platform_device
*pdev
)
186 struct device
*dev
= &pdev
->dev
;
187 unsigned int i
, base
;
189 struct hd44780_common
*hdc
;
191 int ifwidth
, ret
= -ENOMEM
;
194 ifwidth
= gpiod_count(dev
, "data");
209 hdc
= hd44780_common_alloc();
213 lcd
= charlcd_alloc();
217 hd
= kzalloc(sizeof(struct hd44780
), GFP_KERNEL
);
223 for (i
= 0; i
< ifwidth
; i
++) {
224 hd
->pins
[base
+ i
] = devm_gpiod_get_index(dev
, "data", i
,
226 if (IS_ERR(hd
->pins
[base
+ i
])) {
227 ret
= PTR_ERR(hd
->pins
[base
+ i
]);
232 hd
->pins
[PIN_CTRL_E
] = devm_gpiod_get(dev
, "enable", GPIOD_OUT_LOW
);
233 if (IS_ERR(hd
->pins
[PIN_CTRL_E
])) {
234 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_E
]);
238 hd
->pins
[PIN_CTRL_RS
] = devm_gpiod_get(dev
, "rs", GPIOD_OUT_HIGH
);
239 if (IS_ERR(hd
->pins
[PIN_CTRL_RS
])) {
240 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_RS
]);
245 hd
->pins
[PIN_CTRL_RW
] = devm_gpiod_get_optional(dev
, "rw",
247 if (IS_ERR(hd
->pins
[PIN_CTRL_RW
])) {
248 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_RW
]);
252 hd
->pins
[PIN_CTRL_BL
] = devm_gpiod_get_optional(dev
, "backlight",
254 if (IS_ERR(hd
->pins
[PIN_CTRL_BL
])) {
255 ret
= PTR_ERR(hd
->pins
[PIN_CTRL_BL
]);
259 /* Required properties */
260 ret
= device_property_read_u32(dev
, "display-height-chars",
264 ret
= device_property_read_u32(dev
, "display-width-chars", &lcd
->width
);
269 * On displays with more than two rows, the internal buffer width is
270 * usually equal to the display width
273 hdc
->bwidth
= lcd
->width
;
275 /* Optional properties */
276 device_property_read_u32(dev
, "internal-buffer-width", &hdc
->bwidth
);
278 hdc
->ifwidth
= ifwidth
;
280 lcd
->ops
= &hd44780_ops_gpio8
;
281 hdc
->write_data
= hd44780_write_data_gpio8
;
282 hdc
->write_cmd
= hd44780_write_cmd_gpio8
;
284 lcd
->ops
= &hd44780_ops_gpio4
;
285 hdc
->write_data
= hd44780_write_data_gpio4
;
286 hdc
->write_cmd
= hd44780_write_cmd_gpio4
;
287 hdc
->write_cmd_raw4
= hd44780_write_cmd_raw_gpio4
;
290 ret
= charlcd_register(lcd
);
294 platform_set_drvdata(pdev
, lcd
);
306 static int hd44780_remove(struct platform_device
*pdev
)
308 struct charlcd
*lcd
= platform_get_drvdata(pdev
);
311 charlcd_unregister(lcd
);
317 static const struct of_device_id hd44780_of_match
[] = {
318 { .compatible
= "hit,hd44780" },
321 MODULE_DEVICE_TABLE(of
, hd44780_of_match
);
323 static struct platform_driver hd44780_driver
= {
324 .probe
= hd44780_probe
,
325 .remove
= hd44780_remove
,
328 .of_match_table
= hd44780_of_match
,
332 module_platform_driver(hd44780_driver
);
333 MODULE_DESCRIPTION("HD44780 Character LCD driver");
334 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
335 MODULE_LICENSE("GPL");