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/mod_devicetable.h> 13 #include <linux/platform_device.h> 14 #include <linux/property.h> 15 #include <linux/slab.h> 16 17 #include "charlcd.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, int on) 41 { 42 struct hd44780 *hd = lcd->drvdata; 43 44 if (hd->pins[PIN_CTRL_BL]) 45 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_BL], on); 46 } 47 48 static void hd44780_strobe_gpio(struct hd44780 *hd) 49 { 50 /* Maintain the data during 20 us before the strobe */ 51 udelay(20); 52 53 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 1); 54 55 /* Maintain the strobe during 40 us */ 56 udelay(40); 57 58 gpiod_set_value_cansleep(hd->pins[PIN_CTRL_E], 0); 59 } 60 61 /* write to an LCD panel register in 8 bit GPIO mode */ 62 static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs) 63 { 64 DECLARE_BITMAP(values, 10); /* for DATA[0-7], RS, RW */ 65 unsigned int n; 66 67 values[0] = val; 68 __assign_bit(8, values, rs); 69 n = hd->pins[PIN_CTRL_RW] ? 10 : 9; 70 71 /* Present the data to the port */ 72 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], NULL, values); 73 74 hd44780_strobe_gpio(hd); 75 } 76 77 /* write to an LCD panel register in 4 bit GPIO mode */ 78 static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs) 79 { 80 DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */ 81 unsigned int n; 82 83 /* High nibble + RS, RW */ 84 values[0] = val >> 4; 85 __assign_bit(4, values, rs); 86 n = hd->pins[PIN_CTRL_RW] ? 6 : 5; 87 88 /* Present the data to the port */ 89 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values); 90 91 hd44780_strobe_gpio(hd); 92 93 /* Low nibble */ 94 values[0] &= ~0x0fUL; 95 values[0] |= val & 0x0f; 96 97 /* Present the data to the port */ 98 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values); 99 100 hd44780_strobe_gpio(hd); 101 } 102 103 /* Send a command to the LCD panel in 8 bit GPIO mode */ 104 static void hd44780_write_cmd_gpio8(struct charlcd *lcd, int cmd) 105 { 106 struct hd44780 *hd = lcd->drvdata; 107 108 hd44780_write_gpio8(hd, cmd, 0); 109 110 /* The shortest command takes at least 120 us */ 111 udelay(120); 112 } 113 114 /* Send data to the LCD panel in 8 bit GPIO mode */ 115 static void hd44780_write_data_gpio8(struct charlcd *lcd, int data) 116 { 117 struct hd44780 *hd = lcd->drvdata; 118 119 hd44780_write_gpio8(hd, data, 1); 120 121 /* The shortest data takes at least 45 us */ 122 udelay(45); 123 } 124 125 static const struct charlcd_ops hd44780_ops_gpio8 = { 126 .write_cmd = hd44780_write_cmd_gpio8, 127 .write_data = hd44780_write_data_gpio8, 128 .backlight = hd44780_backlight, 129 }; 130 131 /* Send a command to the LCD panel in 4 bit GPIO mode */ 132 static void hd44780_write_cmd_gpio4(struct charlcd *lcd, int cmd) 133 { 134 struct hd44780 *hd = lcd->drvdata; 135 136 hd44780_write_gpio4(hd, cmd, 0); 137 138 /* The shortest command takes at least 120 us */ 139 udelay(120); 140 } 141 142 /* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */ 143 static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd) 144 { 145 DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */ 146 struct hd44780 *hd = lcd->drvdata; 147 unsigned int n; 148 149 /* Command nibble + RS, RW */ 150 values[0] = cmd & 0x0f; 151 n = hd->pins[PIN_CTRL_RW] ? 6 : 5; 152 153 /* Present the data to the port */ 154 gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values); 155 156 hd44780_strobe_gpio(hd); 157 } 158 159 /* Send data to the LCD panel in 4 bit GPIO mode */ 160 static void hd44780_write_data_gpio4(struct charlcd *lcd, int data) 161 { 162 struct hd44780 *hd = lcd->drvdata; 163 164 hd44780_write_gpio4(hd, data, 1); 165 166 /* The shortest data takes at least 45 us */ 167 udelay(45); 168 } 169 170 static const struct charlcd_ops hd44780_ops_gpio4 = { 171 .write_cmd = hd44780_write_cmd_gpio4, 172 .write_cmd_raw4 = hd44780_write_cmd_raw_gpio4, 173 .write_data = hd44780_write_data_gpio4, 174 .backlight = hd44780_backlight, 175 }; 176 177 static int hd44780_probe(struct platform_device *pdev) 178 { 179 struct device *dev = &pdev->dev; 180 unsigned int i, base; 181 struct charlcd *lcd; 182 struct hd44780 *hd; 183 int ifwidth, ret; 184 185 /* Required pins */ 186 ifwidth = gpiod_count(dev, "data"); 187 if (ifwidth < 0) 188 return ifwidth; 189 190 switch (ifwidth) { 191 case 4: 192 base = PIN_DATA4; 193 break; 194 case 8: 195 base = PIN_DATA0; 196 break; 197 default: 198 return -EINVAL; 199 } 200 201 lcd = charlcd_alloc(sizeof(struct hd44780)); 202 if (!lcd) 203 return -ENOMEM; 204 205 hd = lcd->drvdata; 206 207 for (i = 0; i < ifwidth; i++) { 208 hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i, 209 GPIOD_OUT_LOW); 210 if (IS_ERR(hd->pins[base + i])) { 211 ret = PTR_ERR(hd->pins[base + i]); 212 goto fail; 213 } 214 } 215 216 hd->pins[PIN_CTRL_E] = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 217 if (IS_ERR(hd->pins[PIN_CTRL_E])) { 218 ret = PTR_ERR(hd->pins[PIN_CTRL_E]); 219 goto fail; 220 } 221 222 hd->pins[PIN_CTRL_RS] = devm_gpiod_get(dev, "rs", GPIOD_OUT_HIGH); 223 if (IS_ERR(hd->pins[PIN_CTRL_RS])) { 224 ret = PTR_ERR(hd->pins[PIN_CTRL_RS]); 225 goto fail; 226 } 227 228 /* Optional pins */ 229 hd->pins[PIN_CTRL_RW] = devm_gpiod_get_optional(dev, "rw", 230 GPIOD_OUT_LOW); 231 if (IS_ERR(hd->pins[PIN_CTRL_RW])) { 232 ret = PTR_ERR(hd->pins[PIN_CTRL_RW]); 233 goto fail; 234 } 235 236 hd->pins[PIN_CTRL_BL] = devm_gpiod_get_optional(dev, "backlight", 237 GPIOD_OUT_LOW); 238 if (IS_ERR(hd->pins[PIN_CTRL_BL])) { 239 ret = PTR_ERR(hd->pins[PIN_CTRL_BL]); 240 goto fail; 241 } 242 243 /* Required properties */ 244 ret = device_property_read_u32(dev, "display-height-chars", 245 &lcd->height); 246 if (ret) 247 goto fail; 248 ret = device_property_read_u32(dev, "display-width-chars", &lcd->width); 249 if (ret) 250 goto fail; 251 252 /* 253 * On displays with more than two rows, the internal buffer width is 254 * usually equal to the display width 255 */ 256 if (lcd->height > 2) 257 lcd->bwidth = lcd->width; 258 259 /* Optional properties */ 260 device_property_read_u32(dev, "internal-buffer-width", &lcd->bwidth); 261 262 lcd->ifwidth = ifwidth; 263 lcd->ops = ifwidth == 8 ? &hd44780_ops_gpio8 : &hd44780_ops_gpio4; 264 265 ret = charlcd_register(lcd); 266 if (ret) 267 goto fail; 268 269 platform_set_drvdata(pdev, lcd); 270 return 0; 271 272 fail: 273 charlcd_free(lcd); 274 return ret; 275 } 276 277 static int hd44780_remove(struct platform_device *pdev) 278 { 279 struct charlcd *lcd = platform_get_drvdata(pdev); 280 281 charlcd_unregister(lcd); 282 283 charlcd_free(lcd); 284 return 0; 285 } 286 287 static const struct of_device_id hd44780_of_match[] = { 288 { .compatible = "hit,hd44780" }, 289 { /* sentinel */ } 290 }; 291 MODULE_DEVICE_TABLE(of, hd44780_of_match); 292 293 static struct platform_driver hd44780_driver = { 294 .probe = hd44780_probe, 295 .remove = hd44780_remove, 296 .driver = { 297 .name = "hd44780", 298 .of_match_table = hd44780_of_match, 299 }, 300 }; 301 302 module_platform_driver(hd44780_driver); 303 MODULE_DESCRIPTION("HD44780 Character LCD driver"); 304 MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); 305 MODULE_LICENSE("GPL"); 306