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