1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * NBUS driver for TS-4600 based boards 4 * 5 * Copyright (c) 2016 - Savoir-faire Linux 6 * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com> 7 * 8 * This driver implements a GPIOs bit-banged bus, called the NBUS by Technologic 9 * Systems. It is used to communicate with the peripherals in the FPGA on the 10 * TS-4600 SoM. 11 */ 12 13 #include <linux/bitops.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/mutex.h> 18 #include <linux/of_platform.h> 19 #include <linux/platform_device.h> 20 #include <linux/pwm.h> 21 #include <linux/ts-nbus.h> 22 23 #define TS_NBUS_DIRECTION_IN 0 24 #define TS_NBUS_DIRECTION_OUT 1 25 #define TS_NBUS_WRITE_ADR 0 26 #define TS_NBUS_WRITE_VAL 1 27 28 struct ts_nbus { 29 struct pwm_device *pwm; 30 struct gpio_descs *data; 31 struct gpio_desc *csn; 32 struct gpio_desc *txrx; 33 struct gpio_desc *strobe; 34 struct gpio_desc *ale; 35 struct gpio_desc *rdy; 36 struct mutex lock; 37 }; 38 39 /* 40 * request all gpios required by the bus. 41 */ 42 static int ts_nbus_init_pdata(struct platform_device *pdev, struct ts_nbus 43 *ts_nbus) 44 { 45 ts_nbus->data = devm_gpiod_get_array(&pdev->dev, "ts,data", 46 GPIOD_OUT_HIGH); 47 if (IS_ERR(ts_nbus->data)) { 48 dev_err(&pdev->dev, "failed to retrieve ts,data-gpio from dts\n"); 49 return PTR_ERR(ts_nbus->data); 50 } 51 52 ts_nbus->csn = devm_gpiod_get(&pdev->dev, "ts,csn", GPIOD_OUT_HIGH); 53 if (IS_ERR(ts_nbus->csn)) { 54 dev_err(&pdev->dev, "failed to retrieve ts,csn-gpio from dts\n"); 55 return PTR_ERR(ts_nbus->csn); 56 } 57 58 ts_nbus->txrx = devm_gpiod_get(&pdev->dev, "ts,txrx", GPIOD_OUT_HIGH); 59 if (IS_ERR(ts_nbus->txrx)) { 60 dev_err(&pdev->dev, "failed to retrieve ts,txrx-gpio from dts\n"); 61 return PTR_ERR(ts_nbus->txrx); 62 } 63 64 ts_nbus->strobe = devm_gpiod_get(&pdev->dev, "ts,strobe", GPIOD_OUT_HIGH); 65 if (IS_ERR(ts_nbus->strobe)) { 66 dev_err(&pdev->dev, "failed to retrieve ts,strobe-gpio from dts\n"); 67 return PTR_ERR(ts_nbus->strobe); 68 } 69 70 ts_nbus->ale = devm_gpiod_get(&pdev->dev, "ts,ale", GPIOD_OUT_HIGH); 71 if (IS_ERR(ts_nbus->ale)) { 72 dev_err(&pdev->dev, "failed to retrieve ts,ale-gpio from dts\n"); 73 return PTR_ERR(ts_nbus->ale); 74 } 75 76 ts_nbus->rdy = devm_gpiod_get(&pdev->dev, "ts,rdy", GPIOD_IN); 77 if (IS_ERR(ts_nbus->rdy)) { 78 dev_err(&pdev->dev, "failed to retrieve ts,rdy-gpio from dts\n"); 79 return PTR_ERR(ts_nbus->rdy); 80 } 81 82 return 0; 83 } 84 85 /* 86 * the data gpios are used for reading and writing values, their directions 87 * should be adjusted accordingly. 88 */ 89 static void ts_nbus_set_direction(struct ts_nbus *ts_nbus, int direction) 90 { 91 int i; 92 93 for (i = 0; i < 8; i++) { 94 if (direction == TS_NBUS_DIRECTION_IN) 95 gpiod_direction_input(ts_nbus->data->desc[i]); 96 else 97 /* when used as output the default state of the data 98 * lines are set to high */ 99 gpiod_direction_output(ts_nbus->data->desc[i], 1); 100 } 101 } 102 103 /* 104 * reset the bus in its initial state. 105 * The data, csn, strobe and ale lines must be zero'ed to let the FPGA knows a 106 * new transaction can be process. 107 */ 108 static void ts_nbus_reset_bus(struct ts_nbus *ts_nbus) 109 { 110 DECLARE_BITMAP(values, 8); 111 112 values[0] = 0; 113 114 gpiod_set_array_value_cansleep(8, ts_nbus->data->desc, 115 ts_nbus->data->info, values); 116 gpiod_set_value_cansleep(ts_nbus->csn, 0); 117 gpiod_set_value_cansleep(ts_nbus->strobe, 0); 118 gpiod_set_value_cansleep(ts_nbus->ale, 0); 119 } 120 121 /* 122 * let the FPGA knows it can process. 123 */ 124 static void ts_nbus_start_transaction(struct ts_nbus *ts_nbus) 125 { 126 gpiod_set_value_cansleep(ts_nbus->strobe, 1); 127 } 128 129 /* 130 * read a byte value from the data gpios. 131 * return 0 on success or negative errno on failure. 132 */ 133 static int ts_nbus_read_byte(struct ts_nbus *ts_nbus, u8 *val) 134 { 135 struct gpio_descs *gpios = ts_nbus->data; 136 int ret, i; 137 138 *val = 0; 139 for (i = 0; i < 8; i++) { 140 ret = gpiod_get_value_cansleep(gpios->desc[i]); 141 if (ret < 0) 142 return ret; 143 if (ret) 144 *val |= BIT(i); 145 } 146 147 return 0; 148 } 149 150 /* 151 * set the data gpios accordingly to the byte value. 152 */ 153 static void ts_nbus_write_byte(struct ts_nbus *ts_nbus, u8 byte) 154 { 155 struct gpio_descs *gpios = ts_nbus->data; 156 DECLARE_BITMAP(values, 8); 157 158 values[0] = byte; 159 160 gpiod_set_array_value_cansleep(8, gpios->desc, gpios->info, values); 161 } 162 163 /* 164 * reading the bus consists of resetting the bus, then notifying the FPGA to 165 * send the data in the data gpios and return the read value. 166 * return 0 on success or negative errno on failure. 167 */ 168 static int ts_nbus_read_bus(struct ts_nbus *ts_nbus, u8 *val) 169 { 170 ts_nbus_reset_bus(ts_nbus); 171 ts_nbus_start_transaction(ts_nbus); 172 173 return ts_nbus_read_byte(ts_nbus, val); 174 } 175 176 /* 177 * writing to the bus consists of resetting the bus, then define the type of 178 * command (address/value), write the data and notify the FPGA to retrieve the 179 * value in the data gpios. 180 */ 181 static void ts_nbus_write_bus(struct ts_nbus *ts_nbus, int cmd, u8 val) 182 { 183 ts_nbus_reset_bus(ts_nbus); 184 185 if (cmd == TS_NBUS_WRITE_ADR) 186 gpiod_set_value_cansleep(ts_nbus->ale, 1); 187 188 ts_nbus_write_byte(ts_nbus, val); 189 ts_nbus_start_transaction(ts_nbus); 190 } 191 192 /* 193 * read the value in the FPGA register at the given address. 194 * return 0 on success or negative errno on failure. 195 */ 196 int ts_nbus_read(struct ts_nbus *ts_nbus, u8 adr, u16 *val) 197 { 198 int ret, i; 199 u8 byte; 200 201 /* bus access must be atomic */ 202 mutex_lock(&ts_nbus->lock); 203 204 /* set the bus in read mode */ 205 gpiod_set_value_cansleep(ts_nbus->txrx, 0); 206 207 /* write address */ 208 ts_nbus_write_bus(ts_nbus, TS_NBUS_WRITE_ADR, adr); 209 210 /* set the data gpios direction as input before reading */ 211 ts_nbus_set_direction(ts_nbus, TS_NBUS_DIRECTION_IN); 212 213 /* reading value MSB first */ 214 do { 215 *val = 0; 216 byte = 0; 217 for (i = 1; i >= 0; i--) { 218 /* read a byte from the bus, leave on error */ 219 ret = ts_nbus_read_bus(ts_nbus, &byte); 220 if (ret < 0) 221 goto err; 222 223 /* append the byte read to the final value */ 224 *val |= byte << (i * 8); 225 } 226 gpiod_set_value_cansleep(ts_nbus->csn, 1); 227 ret = gpiod_get_value_cansleep(ts_nbus->rdy); 228 } while (ret); 229 230 err: 231 /* restore the data gpios direction as output after reading */ 232 ts_nbus_set_direction(ts_nbus, TS_NBUS_DIRECTION_OUT); 233 234 mutex_unlock(&ts_nbus->lock); 235 236 return ret; 237 } 238 EXPORT_SYMBOL_GPL(ts_nbus_read); 239 240 /* 241 * write the desired value in the FPGA register at the given address. 242 */ 243 int ts_nbus_write(struct ts_nbus *ts_nbus, u8 adr, u16 val) 244 { 245 int i; 246 247 /* bus access must be atomic */ 248 mutex_lock(&ts_nbus->lock); 249 250 /* set the bus in write mode */ 251 gpiod_set_value_cansleep(ts_nbus->txrx, 1); 252 253 /* write address */ 254 ts_nbus_write_bus(ts_nbus, TS_NBUS_WRITE_ADR, adr); 255 256 /* writing value MSB first */ 257 for (i = 1; i >= 0; i--) 258 ts_nbus_write_bus(ts_nbus, TS_NBUS_WRITE_VAL, (u8)(val >> (i * 8))); 259 260 /* wait for completion */ 261 gpiod_set_value_cansleep(ts_nbus->csn, 1); 262 while (gpiod_get_value_cansleep(ts_nbus->rdy) != 0) { 263 gpiod_set_value_cansleep(ts_nbus->csn, 0); 264 gpiod_set_value_cansleep(ts_nbus->csn, 1); 265 } 266 267 mutex_unlock(&ts_nbus->lock); 268 269 return 0; 270 } 271 EXPORT_SYMBOL_GPL(ts_nbus_write); 272 273 static int ts_nbus_probe(struct platform_device *pdev) 274 { 275 struct pwm_device *pwm; 276 struct pwm_args pargs; 277 struct device *dev = &pdev->dev; 278 struct ts_nbus *ts_nbus; 279 int ret; 280 281 ts_nbus = devm_kzalloc(dev, sizeof(*ts_nbus), GFP_KERNEL); 282 if (!ts_nbus) 283 return -ENOMEM; 284 285 mutex_init(&ts_nbus->lock); 286 287 ret = ts_nbus_init_pdata(pdev, ts_nbus); 288 if (ret < 0) 289 return ret; 290 291 pwm = devm_pwm_get(dev, NULL); 292 if (IS_ERR(pwm)) { 293 ret = PTR_ERR(pwm); 294 if (ret != -EPROBE_DEFER) 295 dev_err(dev, "unable to request PWM\n"); 296 return ret; 297 } 298 299 pwm_get_args(pwm, &pargs); 300 if (!pargs.period) { 301 dev_err(&pdev->dev, "invalid PWM period\n"); 302 return -EINVAL; 303 } 304 305 /* 306 * FIXME: pwm_apply_args() should be removed when switching to 307 * the atomic PWM API. 308 */ 309 pwm_apply_args(pwm); 310 ret = pwm_config(pwm, pargs.period, pargs.period); 311 if (ret < 0) 312 return ret; 313 314 /* 315 * we can now start the FPGA and populate the peripherals. 316 */ 317 pwm_enable(pwm); 318 ts_nbus->pwm = pwm; 319 320 /* 321 * let the child nodes retrieve this instance of the ts-nbus. 322 */ 323 dev_set_drvdata(dev, ts_nbus); 324 325 ret = of_platform_populate(dev->of_node, NULL, NULL, dev); 326 if (ret < 0) 327 return ret; 328 329 dev_info(dev, "initialized\n"); 330 331 return 0; 332 } 333 334 static void ts_nbus_remove(struct platform_device *pdev) 335 { 336 struct ts_nbus *ts_nbus = dev_get_drvdata(&pdev->dev); 337 338 /* shutdown the FPGA */ 339 mutex_lock(&ts_nbus->lock); 340 pwm_disable(ts_nbus->pwm); 341 mutex_unlock(&ts_nbus->lock); 342 } 343 344 static const struct of_device_id ts_nbus_of_match[] = { 345 { .compatible = "technologic,ts-nbus", }, 346 { }, 347 }; 348 MODULE_DEVICE_TABLE(of, ts_nbus_of_match); 349 350 static struct platform_driver ts_nbus_driver = { 351 .probe = ts_nbus_probe, 352 .remove_new = ts_nbus_remove, 353 .driver = { 354 .name = "ts_nbus", 355 .of_match_table = ts_nbus_of_match, 356 }, 357 }; 358 359 module_platform_driver(ts_nbus_driver); 360 361 MODULE_ALIAS("platform:ts_nbus"); 362 MODULE_AUTHOR("Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>"); 363 MODULE_DESCRIPTION("Technologic Systems NBUS"); 364 MODULE_LICENSE("GPL v2"); 365