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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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