1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 23ce8859eSGuenter Roeck /* 33ce8859eSGuenter Roeck * NXP SC18IS602/603 SPI driver 43ce8859eSGuenter Roeck * 53ce8859eSGuenter Roeck * Copyright (C) Guenter Roeck <linux@roeck-us.net> 63ce8859eSGuenter Roeck */ 73ce8859eSGuenter Roeck 83ce8859eSGuenter Roeck #include <linux/kernel.h> 93ce8859eSGuenter Roeck #include <linux/err.h> 103ce8859eSGuenter Roeck #include <linux/module.h> 113ce8859eSGuenter Roeck #include <linux/spi/spi.h> 123ce8859eSGuenter Roeck #include <linux/i2c.h> 133ce8859eSGuenter Roeck #include <linux/delay.h> 143ce8859eSGuenter Roeck #include <linux/pm_runtime.h> 1568c97b92SJavier Martinez Canillas #include <linux/of_device.h> 163ce8859eSGuenter Roeck #include <linux/of.h> 173ce8859eSGuenter Roeck #include <linux/platform_data/sc18is602.h> 18f9900801SPhil Reid #include <linux/gpio/consumer.h> 193ce8859eSGuenter Roeck 203ce8859eSGuenter Roeck enum chips { sc18is602, sc18is602b, sc18is603 }; 213ce8859eSGuenter Roeck 223ce8859eSGuenter Roeck #define SC18IS602_BUFSIZ 200 233ce8859eSGuenter Roeck #define SC18IS602_CLOCK 7372000 243ce8859eSGuenter Roeck 253ce8859eSGuenter Roeck #define SC18IS602_MODE_CPHA BIT(2) 263ce8859eSGuenter Roeck #define SC18IS602_MODE_CPOL BIT(3) 273ce8859eSGuenter Roeck #define SC18IS602_MODE_LSB_FIRST BIT(5) 283ce8859eSGuenter Roeck #define SC18IS602_MODE_CLOCK_DIV_4 0x0 293ce8859eSGuenter Roeck #define SC18IS602_MODE_CLOCK_DIV_16 0x1 303ce8859eSGuenter Roeck #define SC18IS602_MODE_CLOCK_DIV_64 0x2 313ce8859eSGuenter Roeck #define SC18IS602_MODE_CLOCK_DIV_128 0x3 323ce8859eSGuenter Roeck 333ce8859eSGuenter Roeck struct sc18is602 { 343ce8859eSGuenter Roeck struct spi_master *master; 353ce8859eSGuenter Roeck struct device *dev; 363ce8859eSGuenter Roeck u8 ctrl; 373ce8859eSGuenter Roeck u32 freq; 383ce8859eSGuenter Roeck u32 speed; 393ce8859eSGuenter Roeck 403ce8859eSGuenter Roeck /* I2C data */ 413ce8859eSGuenter Roeck struct i2c_client *client; 423ce8859eSGuenter Roeck enum chips id; 433ce8859eSGuenter Roeck u8 buffer[SC18IS602_BUFSIZ + 1]; 443ce8859eSGuenter Roeck int tlen; /* Data queued for tx in buffer */ 453ce8859eSGuenter Roeck int rindex; /* Receive data index in buffer */ 46f9900801SPhil Reid 47f9900801SPhil Reid struct gpio_desc *reset; 483ce8859eSGuenter Roeck }; 493ce8859eSGuenter Roeck 503ce8859eSGuenter Roeck static int sc18is602_wait_ready(struct sc18is602 *hw, int len) 513ce8859eSGuenter Roeck { 523ce8859eSGuenter Roeck int i, err; 533ce8859eSGuenter Roeck int usecs = 1000000 * len / hw->speed + 1; 543ce8859eSGuenter Roeck u8 dummy[1]; 553ce8859eSGuenter Roeck 563ce8859eSGuenter Roeck for (i = 0; i < 10; i++) { 573ce8859eSGuenter Roeck err = i2c_master_recv(hw->client, dummy, 1); 583ce8859eSGuenter Roeck if (err >= 0) 593ce8859eSGuenter Roeck return 0; 603ce8859eSGuenter Roeck usleep_range(usecs, usecs * 2); 613ce8859eSGuenter Roeck } 623ce8859eSGuenter Roeck return -ETIMEDOUT; 633ce8859eSGuenter Roeck } 643ce8859eSGuenter Roeck 653ce8859eSGuenter Roeck static int sc18is602_txrx(struct sc18is602 *hw, struct spi_message *msg, 663ce8859eSGuenter Roeck struct spi_transfer *t, bool do_transfer) 673ce8859eSGuenter Roeck { 683ce8859eSGuenter Roeck unsigned int len = t->len; 693ce8859eSGuenter Roeck int ret; 703ce8859eSGuenter Roeck 713ce8859eSGuenter Roeck if (hw->tlen == 0) { 723ce8859eSGuenter Roeck /* First byte (I2C command) is chip select */ 733ce8859eSGuenter Roeck hw->buffer[0] = 1 << msg->spi->chip_select; 743ce8859eSGuenter Roeck hw->tlen = 1; 753ce8859eSGuenter Roeck hw->rindex = 0; 763ce8859eSGuenter Roeck } 773ce8859eSGuenter Roeck /* 783ce8859eSGuenter Roeck * We can not immediately send data to the chip, since each I2C message 793ce8859eSGuenter Roeck * resembles a full SPI message (from CS active to CS inactive). 803ce8859eSGuenter Roeck * Enqueue messages up to the first read or until do_transfer is true. 813ce8859eSGuenter Roeck */ 823ce8859eSGuenter Roeck if (t->tx_buf) { 833ce8859eSGuenter Roeck memcpy(&hw->buffer[hw->tlen], t->tx_buf, len); 843ce8859eSGuenter Roeck hw->tlen += len; 853ce8859eSGuenter Roeck if (t->rx_buf) 863ce8859eSGuenter Roeck do_transfer = true; 873ce8859eSGuenter Roeck else 883ce8859eSGuenter Roeck hw->rindex = hw->tlen - 1; 893ce8859eSGuenter Roeck } else if (t->rx_buf) { 903ce8859eSGuenter Roeck /* 913ce8859eSGuenter Roeck * For receive-only transfers we still need to perform a dummy 923ce8859eSGuenter Roeck * write to receive data from the SPI chip. 933ce8859eSGuenter Roeck * Read data starts at the end of transmit data (minus 1 to 943ce8859eSGuenter Roeck * account for CS). 953ce8859eSGuenter Roeck */ 963ce8859eSGuenter Roeck hw->rindex = hw->tlen - 1; 973ce8859eSGuenter Roeck memset(&hw->buffer[hw->tlen], 0, len); 983ce8859eSGuenter Roeck hw->tlen += len; 993ce8859eSGuenter Roeck do_transfer = true; 1003ce8859eSGuenter Roeck } 1013ce8859eSGuenter Roeck 1023ce8859eSGuenter Roeck if (do_transfer && hw->tlen > 1) { 1033ce8859eSGuenter Roeck ret = sc18is602_wait_ready(hw, SC18IS602_BUFSIZ); 1043ce8859eSGuenter Roeck if (ret < 0) 1053ce8859eSGuenter Roeck return ret; 1063ce8859eSGuenter Roeck ret = i2c_master_send(hw->client, hw->buffer, hw->tlen); 1073ce8859eSGuenter Roeck if (ret < 0) 1083ce8859eSGuenter Roeck return ret; 1093ce8859eSGuenter Roeck if (ret != hw->tlen) 1103ce8859eSGuenter Roeck return -EIO; 1113ce8859eSGuenter Roeck 1123ce8859eSGuenter Roeck if (t->rx_buf) { 1133ce8859eSGuenter Roeck int rlen = hw->rindex + len; 1143ce8859eSGuenter Roeck 1153ce8859eSGuenter Roeck ret = sc18is602_wait_ready(hw, hw->tlen); 1163ce8859eSGuenter Roeck if (ret < 0) 1173ce8859eSGuenter Roeck return ret; 1183ce8859eSGuenter Roeck ret = i2c_master_recv(hw->client, hw->buffer, rlen); 1193ce8859eSGuenter Roeck if (ret < 0) 1203ce8859eSGuenter Roeck return ret; 1213ce8859eSGuenter Roeck if (ret != rlen) 1223ce8859eSGuenter Roeck return -EIO; 1233ce8859eSGuenter Roeck memcpy(t->rx_buf, &hw->buffer[hw->rindex], len); 1243ce8859eSGuenter Roeck } 1253ce8859eSGuenter Roeck hw->tlen = 0; 1263ce8859eSGuenter Roeck } 1273ce8859eSGuenter Roeck return len; 1283ce8859eSGuenter Roeck } 1293ce8859eSGuenter Roeck 1303ce8859eSGuenter Roeck static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode) 1313ce8859eSGuenter Roeck { 1323ce8859eSGuenter Roeck u8 ctrl = 0; 1333ce8859eSGuenter Roeck int ret; 1343ce8859eSGuenter Roeck 1353ce8859eSGuenter Roeck if (mode & SPI_CPHA) 1363ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_CPHA; 1373ce8859eSGuenter Roeck if (mode & SPI_CPOL) 1383ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_CPOL; 1393ce8859eSGuenter Roeck if (mode & SPI_LSB_FIRST) 1403ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_LSB_FIRST; 1413ce8859eSGuenter Roeck 1423ce8859eSGuenter Roeck /* Find the closest clock speed */ 1433ce8859eSGuenter Roeck if (hz >= hw->freq / 4) { 1443ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_CLOCK_DIV_4; 1453ce8859eSGuenter Roeck hw->speed = hw->freq / 4; 1463ce8859eSGuenter Roeck } else if (hz >= hw->freq / 16) { 1473ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_CLOCK_DIV_16; 1483ce8859eSGuenter Roeck hw->speed = hw->freq / 16; 1493ce8859eSGuenter Roeck } else if (hz >= hw->freq / 64) { 1503ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_CLOCK_DIV_64; 1513ce8859eSGuenter Roeck hw->speed = hw->freq / 64; 1523ce8859eSGuenter Roeck } else { 1533ce8859eSGuenter Roeck ctrl |= SC18IS602_MODE_CLOCK_DIV_128; 1543ce8859eSGuenter Roeck hw->speed = hw->freq / 128; 1553ce8859eSGuenter Roeck } 1563ce8859eSGuenter Roeck 1573ce8859eSGuenter Roeck /* 1583ce8859eSGuenter Roeck * Don't do anything if the control value did not change. The initial 1593ce8859eSGuenter Roeck * value of 0xff for hw->ctrl ensures that the correct mode will be set 1603ce8859eSGuenter Roeck * with the first call to this function. 1613ce8859eSGuenter Roeck */ 1623ce8859eSGuenter Roeck if (ctrl == hw->ctrl) 1633ce8859eSGuenter Roeck return 0; 1643ce8859eSGuenter Roeck 1653ce8859eSGuenter Roeck ret = i2c_smbus_write_byte_data(hw->client, 0xf0, ctrl); 1663ce8859eSGuenter Roeck if (ret < 0) 1673ce8859eSGuenter Roeck return ret; 1683ce8859eSGuenter Roeck 1693ce8859eSGuenter Roeck hw->ctrl = ctrl; 1703ce8859eSGuenter Roeck 1713ce8859eSGuenter Roeck return 0; 1723ce8859eSGuenter Roeck } 1733ce8859eSGuenter Roeck 1743ce8859eSGuenter Roeck static int sc18is602_check_transfer(struct spi_device *spi, 1753ce8859eSGuenter Roeck struct spi_transfer *t, int tlen) 1763ce8859eSGuenter Roeck { 1773ce8859eSGuenter Roeck if (t && t->len + tlen > SC18IS602_BUFSIZ) 1783ce8859eSGuenter Roeck return -EINVAL; 1793ce8859eSGuenter Roeck 1803ce8859eSGuenter Roeck return 0; 1813ce8859eSGuenter Roeck } 1823ce8859eSGuenter Roeck 1833ce8859eSGuenter Roeck static int sc18is602_transfer_one(struct spi_master *master, 1843ce8859eSGuenter Roeck struct spi_message *m) 1853ce8859eSGuenter Roeck { 1863ce8859eSGuenter Roeck struct sc18is602 *hw = spi_master_get_devdata(master); 1873ce8859eSGuenter Roeck struct spi_device *spi = m->spi; 1883ce8859eSGuenter Roeck struct spi_transfer *t; 1893ce8859eSGuenter Roeck int status = 0; 1903ce8859eSGuenter Roeck 1913ce8859eSGuenter Roeck hw->tlen = 0; 1923ce8859eSGuenter Roeck list_for_each_entry(t, &m->transfers, transfer_list) { 1933ce8859eSGuenter Roeck bool do_transfer; 1943ce8859eSGuenter Roeck 1953ce8859eSGuenter Roeck status = sc18is602_check_transfer(spi, t, hw->tlen); 1963ce8859eSGuenter Roeck if (status < 0) 1973ce8859eSGuenter Roeck break; 1983ce8859eSGuenter Roeck 19909e99bcaSAxel Lin status = sc18is602_setup_transfer(hw, t->speed_hz, spi->mode); 2003ce8859eSGuenter Roeck if (status < 0) 2013ce8859eSGuenter Roeck break; 2023ce8859eSGuenter Roeck 2033ce8859eSGuenter Roeck do_transfer = t->cs_change || list_is_last(&t->transfer_list, 2043ce8859eSGuenter Roeck &m->transfers); 2053ce8859eSGuenter Roeck 2063ce8859eSGuenter Roeck if (t->len) { 2073ce8859eSGuenter Roeck status = sc18is602_txrx(hw, m, t, do_transfer); 2083ce8859eSGuenter Roeck if (status < 0) 2093ce8859eSGuenter Roeck break; 2103ce8859eSGuenter Roeck m->actual_length += status; 2113ce8859eSGuenter Roeck } 2123ce8859eSGuenter Roeck status = 0; 2133ce8859eSGuenter Roeck 214e74dc5c7SAlexandru Ardelean spi_transfer_delay_exec(t); 2153ce8859eSGuenter Roeck } 2163ce8859eSGuenter Roeck m->status = status; 2173ce8859eSGuenter Roeck spi_finalize_current_message(master); 2183ce8859eSGuenter Roeck 2193ce8859eSGuenter Roeck return status; 2203ce8859eSGuenter Roeck } 2213ce8859eSGuenter Roeck 222c5c67e31SAxel Lin static int sc18is602_setup(struct spi_device *spi) 223c5c67e31SAxel Lin { 224c5c67e31SAxel Lin struct sc18is602 *hw = spi_master_get_devdata(spi->master); 225c5c67e31SAxel Lin 226c5c67e31SAxel Lin /* SC18IS602 does not support CS2 */ 227c5c67e31SAxel Lin if (hw->id == sc18is602 && spi->chip_select == 2) 228c5c67e31SAxel Lin return -ENXIO; 229c5c67e31SAxel Lin 230c5c67e31SAxel Lin return 0; 231c5c67e31SAxel Lin } 232c5c67e31SAxel Lin 2333ce8859eSGuenter Roeck static int sc18is602_probe(struct i2c_client *client, 2343ce8859eSGuenter Roeck const struct i2c_device_id *id) 2353ce8859eSGuenter Roeck { 2363ce8859eSGuenter Roeck struct device *dev = &client->dev; 2373ce8859eSGuenter Roeck struct device_node *np = dev->of_node; 2383ce8859eSGuenter Roeck struct sc18is602_platform_data *pdata = dev_get_platdata(dev); 2393ce8859eSGuenter Roeck struct sc18is602 *hw; 2403ce8859eSGuenter Roeck struct spi_master *master; 2413ce8859eSGuenter Roeck int error; 2423ce8859eSGuenter Roeck 2433ce8859eSGuenter Roeck if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | 2443ce8859eSGuenter Roeck I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) 24558ed90deSGuenter Roeck return -EINVAL; 2463ce8859eSGuenter Roeck 2473ce8859eSGuenter Roeck master = spi_alloc_master(dev, sizeof(struct sc18is602)); 2483ce8859eSGuenter Roeck if (!master) 2493ce8859eSGuenter Roeck return -ENOMEM; 2503ce8859eSGuenter Roeck 2513ce8859eSGuenter Roeck hw = spi_master_get_devdata(master); 2523ce8859eSGuenter Roeck i2c_set_clientdata(client, hw); 2533ce8859eSGuenter Roeck 254f9900801SPhil Reid /* assert reset and then release */ 255f9900801SPhil Reid hw->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 256f9900801SPhil Reid if (IS_ERR(hw->reset)) 257f9900801SPhil Reid return PTR_ERR(hw->reset); 25876cce7e3SPhil Reid gpiod_set_value_cansleep(hw->reset, 0); 259f9900801SPhil Reid 2603ce8859eSGuenter Roeck hw->master = master; 2613ce8859eSGuenter Roeck hw->client = client; 2623ce8859eSGuenter Roeck hw->dev = dev; 2633ce8859eSGuenter Roeck hw->ctrl = 0xff; 2643ce8859eSGuenter Roeck 26568c97b92SJavier Martinez Canillas if (client->dev.of_node) 26668c97b92SJavier Martinez Canillas hw->id = (enum chips)of_device_get_match_data(&client->dev); 26768c97b92SJavier Martinez Canillas else 2683ce8859eSGuenter Roeck hw->id = id->driver_data; 2693ce8859eSGuenter Roeck 2703ce8859eSGuenter Roeck switch (hw->id) { 2713ce8859eSGuenter Roeck case sc18is602: 2723ce8859eSGuenter Roeck case sc18is602b: 2733ce8859eSGuenter Roeck master->num_chipselect = 4; 2743ce8859eSGuenter Roeck hw->freq = SC18IS602_CLOCK; 2753ce8859eSGuenter Roeck break; 2763ce8859eSGuenter Roeck case sc18is603: 2773ce8859eSGuenter Roeck master->num_chipselect = 2; 2783ce8859eSGuenter Roeck if (pdata) { 2793ce8859eSGuenter Roeck hw->freq = pdata->clock_frequency; 2803ce8859eSGuenter Roeck } else { 2813ce8859eSGuenter Roeck const __be32 *val; 2823ce8859eSGuenter Roeck int len; 2833ce8859eSGuenter Roeck 2843ce8859eSGuenter Roeck val = of_get_property(np, "clock-frequency", &len); 2853ce8859eSGuenter Roeck if (val && len >= sizeof(__be32)) 2863ce8859eSGuenter Roeck hw->freq = be32_to_cpup(val); 2873ce8859eSGuenter Roeck } 2883ce8859eSGuenter Roeck if (!hw->freq) 2893ce8859eSGuenter Roeck hw->freq = SC18IS602_CLOCK; 2903ce8859eSGuenter Roeck break; 2913ce8859eSGuenter Roeck } 292b4e27545SGuenter Roeck master->bus_num = np ? -1 : client->adapter->nr; 2933ce8859eSGuenter Roeck master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST; 294463654ceSAxel Lin master->bits_per_word_mask = SPI_BPW_MASK(8); 295c5c67e31SAxel Lin master->setup = sc18is602_setup; 2963ce8859eSGuenter Roeck master->transfer_one_message = sc18is602_transfer_one; 2973ce8859eSGuenter Roeck master->dev.of_node = np; 29809e99bcaSAxel Lin master->min_speed_hz = hw->freq / 128; 29909e99bcaSAxel Lin master->max_speed_hz = hw->freq / 4; 3003ce8859eSGuenter Roeck 30115e0964dSJingoo Han error = devm_spi_register_master(dev, master); 3023ce8859eSGuenter Roeck if (error) 3033ce8859eSGuenter Roeck goto error_reg; 3043ce8859eSGuenter Roeck 3053ce8859eSGuenter Roeck return 0; 3063ce8859eSGuenter Roeck 3073ce8859eSGuenter Roeck error_reg: 3083ce8859eSGuenter Roeck spi_master_put(master); 3093ce8859eSGuenter Roeck return error; 3103ce8859eSGuenter Roeck } 3113ce8859eSGuenter Roeck 3123ce8859eSGuenter Roeck static const struct i2c_device_id sc18is602_id[] = { 3133ce8859eSGuenter Roeck { "sc18is602", sc18is602 }, 3143ce8859eSGuenter Roeck { "sc18is602b", sc18is602b }, 3153ce8859eSGuenter Roeck { "sc18is603", sc18is603 }, 3163ce8859eSGuenter Roeck { } 3173ce8859eSGuenter Roeck }; 3183ce8859eSGuenter Roeck MODULE_DEVICE_TABLE(i2c, sc18is602_id); 3193ce8859eSGuenter Roeck 32068c97b92SJavier Martinez Canillas static const struct of_device_id sc18is602_of_match[] = { 32168c97b92SJavier Martinez Canillas { 32268c97b92SJavier Martinez Canillas .compatible = "nxp,sc18is602", 32368c97b92SJavier Martinez Canillas .data = (void *)sc18is602 32468c97b92SJavier Martinez Canillas }, 32568c97b92SJavier Martinez Canillas { 32668c97b92SJavier Martinez Canillas .compatible = "nxp,sc18is602b", 32768c97b92SJavier Martinez Canillas .data = (void *)sc18is602b 32868c97b92SJavier Martinez Canillas }, 32968c97b92SJavier Martinez Canillas { 33068c97b92SJavier Martinez Canillas .compatible = "nxp,sc18is603", 33168c97b92SJavier Martinez Canillas .data = (void *)sc18is603 33268c97b92SJavier Martinez Canillas }, 33368c97b92SJavier Martinez Canillas { }, 33468c97b92SJavier Martinez Canillas }; 33568c97b92SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, sc18is602_of_match); 33668c97b92SJavier Martinez Canillas 3373ce8859eSGuenter Roeck static struct i2c_driver sc18is602_driver = { 3383ce8859eSGuenter Roeck .driver = { 3393ce8859eSGuenter Roeck .name = "sc18is602", 34068c97b92SJavier Martinez Canillas .of_match_table = of_match_ptr(sc18is602_of_match), 3413ce8859eSGuenter Roeck }, 3423ce8859eSGuenter Roeck .probe = sc18is602_probe, 3433ce8859eSGuenter Roeck .id_table = sc18is602_id, 3443ce8859eSGuenter Roeck }; 3453ce8859eSGuenter Roeck 3463ce8859eSGuenter Roeck module_i2c_driver(sc18is602_driver); 3473ce8859eSGuenter Roeck 3483ce8859eSGuenter Roeck MODULE_DESCRIPTION("SC18IC602/603 SPI Master Driver"); 3493ce8859eSGuenter Roeck MODULE_AUTHOR("Guenter Roeck"); 3503ce8859eSGuenter Roeck MODULE_LICENSE("GPL"); 351