134009bffSJacopo Mondi // SPDX-License-Identifier: GPL-2.0+ 234009bffSJacopo Mondi /* 334009bffSJacopo Mondi * Copyright (C) 2017-2020 Jacopo Mondi 434009bffSJacopo Mondi * Copyright (C) 2017-2020 Kieran Bingham 534009bffSJacopo Mondi * Copyright (C) 2017-2020 Laurent Pinchart 634009bffSJacopo Mondi * Copyright (C) 2017-2020 Niklas Söderlund 734009bffSJacopo Mondi * Copyright (C) 2016 Renesas Electronics Corporation 834009bffSJacopo Mondi * Copyright (C) 2015 Cogent Embedded, Inc. 934009bffSJacopo Mondi * 1034009bffSJacopo Mondi * This file exports functions to control the Maxim MAX9271 GMSL serializer 1134009bffSJacopo Mondi * chip. This is not a self-contained driver, as MAX9271 is usually embedded in 1234009bffSJacopo Mondi * camera modules with at least one image sensor and optional additional 1334009bffSJacopo Mondi * components, such as uController units or ISPs/DSPs. 1434009bffSJacopo Mondi * 1534009bffSJacopo Mondi * Drivers for the camera modules (i.e. rdacm20/21) are expected to use 1634009bffSJacopo Mondi * functions exported from this library driver to maximize code re-use. 1734009bffSJacopo Mondi */ 1834009bffSJacopo Mondi 1934009bffSJacopo Mondi #include <linux/delay.h> 2034009bffSJacopo Mondi #include <linux/i2c.h> 21*ce79aecfSJacopo Mondi #include <linux/module.h> 2234009bffSJacopo Mondi 2334009bffSJacopo Mondi #include "max9271.h" 2434009bffSJacopo Mondi 2534009bffSJacopo Mondi static int max9271_read(struct max9271_device *dev, u8 reg) 2634009bffSJacopo Mondi { 2734009bffSJacopo Mondi int ret; 2834009bffSJacopo Mondi 2934009bffSJacopo Mondi dev_dbg(&dev->client->dev, "%s(0x%02x)\n", __func__, reg); 3034009bffSJacopo Mondi 3134009bffSJacopo Mondi ret = i2c_smbus_read_byte_data(dev->client, reg); 3234009bffSJacopo Mondi if (ret < 0) 3334009bffSJacopo Mondi dev_dbg(&dev->client->dev, 3434009bffSJacopo Mondi "%s: register 0x%02x read failed (%d)\n", 3534009bffSJacopo Mondi __func__, reg, ret); 3634009bffSJacopo Mondi 3734009bffSJacopo Mondi return ret; 3834009bffSJacopo Mondi } 3934009bffSJacopo Mondi 4034009bffSJacopo Mondi static int max9271_write(struct max9271_device *dev, u8 reg, u8 val) 4134009bffSJacopo Mondi { 4234009bffSJacopo Mondi int ret; 4334009bffSJacopo Mondi 4434009bffSJacopo Mondi dev_dbg(&dev->client->dev, "%s(0x%02x, 0x%02x)\n", __func__, reg, val); 4534009bffSJacopo Mondi 4634009bffSJacopo Mondi ret = i2c_smbus_write_byte_data(dev->client, reg, val); 4734009bffSJacopo Mondi if (ret < 0) 4834009bffSJacopo Mondi dev_err(&dev->client->dev, 4934009bffSJacopo Mondi "%s: register 0x%02x write failed (%d)\n", 5034009bffSJacopo Mondi __func__, reg, ret); 5134009bffSJacopo Mondi 5234009bffSJacopo Mondi return ret; 5334009bffSJacopo Mondi } 5434009bffSJacopo Mondi 5534009bffSJacopo Mondi /* 5634009bffSJacopo Mondi * max9271_pclk_detect() - Detect valid pixel clock from image sensor 5734009bffSJacopo Mondi * 5834009bffSJacopo Mondi * Wait up to 10ms for a valid pixel clock. 5934009bffSJacopo Mondi * 6034009bffSJacopo Mondi * Returns 0 for success, < 0 for pixel clock not properly detected 6134009bffSJacopo Mondi */ 6234009bffSJacopo Mondi static int max9271_pclk_detect(struct max9271_device *dev) 6334009bffSJacopo Mondi { 6434009bffSJacopo Mondi unsigned int i; 6534009bffSJacopo Mondi int ret; 6634009bffSJacopo Mondi 6734009bffSJacopo Mondi for (i = 0; i < 100; i++) { 6834009bffSJacopo Mondi ret = max9271_read(dev, 0x15); 6934009bffSJacopo Mondi if (ret < 0) 7034009bffSJacopo Mondi return ret; 7134009bffSJacopo Mondi 7234009bffSJacopo Mondi if (ret & MAX9271_PCLKDET) 7334009bffSJacopo Mondi return 0; 7434009bffSJacopo Mondi 7534009bffSJacopo Mondi usleep_range(50, 100); 7634009bffSJacopo Mondi } 7734009bffSJacopo Mondi 7834009bffSJacopo Mondi dev_err(&dev->client->dev, "Unable to detect valid pixel clock\n"); 7934009bffSJacopo Mondi 8034009bffSJacopo Mondi return -EIO; 8134009bffSJacopo Mondi } 8234009bffSJacopo Mondi 8334009bffSJacopo Mondi int max9271_set_serial_link(struct max9271_device *dev, bool enable) 8434009bffSJacopo Mondi { 8534009bffSJacopo Mondi int ret; 8634009bffSJacopo Mondi u8 val = MAX9271_REVCCEN | MAX9271_FWDCCEN; 8734009bffSJacopo Mondi 8834009bffSJacopo Mondi if (enable) { 8934009bffSJacopo Mondi ret = max9271_pclk_detect(dev); 9034009bffSJacopo Mondi if (ret) 9134009bffSJacopo Mondi return ret; 9234009bffSJacopo Mondi 9334009bffSJacopo Mondi val |= MAX9271_SEREN; 9434009bffSJacopo Mondi } else { 9534009bffSJacopo Mondi val |= MAX9271_CLINKEN; 9634009bffSJacopo Mondi } 9734009bffSJacopo Mondi 9834009bffSJacopo Mondi /* 9934009bffSJacopo Mondi * The serializer temporarily disables the reverse control channel for 10034009bffSJacopo Mondi * 350µs after starting/stopping the forward serial link, but the 10134009bffSJacopo Mondi * deserializer synchronization time isn't clearly documented. 10234009bffSJacopo Mondi * 10334009bffSJacopo Mondi * According to the serializer datasheet we should wait 3ms, while 10434009bffSJacopo Mondi * according to the deserializer datasheet we should wait 5ms. 10534009bffSJacopo Mondi * 10634009bffSJacopo Mondi * Short delays here appear to show bit-errors in the writes following. 10734009bffSJacopo Mondi * Therefore a conservative delay seems best here. 10834009bffSJacopo Mondi */ 10934009bffSJacopo Mondi max9271_write(dev, 0x04, val); 11034009bffSJacopo Mondi usleep_range(5000, 8000); 11134009bffSJacopo Mondi 11234009bffSJacopo Mondi return 0; 11334009bffSJacopo Mondi } 11434009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_set_serial_link); 11534009bffSJacopo Mondi 11634009bffSJacopo Mondi int max9271_configure_i2c(struct max9271_device *dev, u8 i2c_config) 11734009bffSJacopo Mondi { 11834009bffSJacopo Mondi int ret; 11934009bffSJacopo Mondi 12034009bffSJacopo Mondi ret = max9271_write(dev, 0x0d, i2c_config); 12134009bffSJacopo Mondi if (ret) 12234009bffSJacopo Mondi return ret; 12334009bffSJacopo Mondi 12434009bffSJacopo Mondi /* The delay required after an I2C bus configuration change is not 12534009bffSJacopo Mondi * characterized in the serializer manual. Sleep up to 5msec to 12634009bffSJacopo Mondi * stay safe. 12734009bffSJacopo Mondi */ 12834009bffSJacopo Mondi usleep_range(3500, 5000); 12934009bffSJacopo Mondi 13034009bffSJacopo Mondi return 0; 13134009bffSJacopo Mondi } 13234009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_configure_i2c); 13334009bffSJacopo Mondi 13434009bffSJacopo Mondi int max9271_set_high_threshold(struct max9271_device *dev, bool enable) 13534009bffSJacopo Mondi { 13634009bffSJacopo Mondi int ret; 13734009bffSJacopo Mondi 13834009bffSJacopo Mondi ret = max9271_read(dev, 0x08); 13934009bffSJacopo Mondi if (ret < 0) 14034009bffSJacopo Mondi return ret; 14134009bffSJacopo Mondi 14234009bffSJacopo Mondi /* 14334009bffSJacopo Mondi * Enable or disable reverse channel high threshold to increase 14434009bffSJacopo Mondi * immunity to power supply noise. 14534009bffSJacopo Mondi */ 14634009bffSJacopo Mondi max9271_write(dev, 0x08, enable ? ret | BIT(0) : ret & ~BIT(0)); 14734009bffSJacopo Mondi usleep_range(2000, 2500); 14834009bffSJacopo Mondi 14934009bffSJacopo Mondi return 0; 15034009bffSJacopo Mondi } 15134009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_set_high_threshold); 15234009bffSJacopo Mondi 15334009bffSJacopo Mondi int max9271_configure_gmsl_link(struct max9271_device *dev) 15434009bffSJacopo Mondi { 15534009bffSJacopo Mondi /* 15634009bffSJacopo Mondi * Configure the GMSL link: 15734009bffSJacopo Mondi * 15834009bffSJacopo Mondi * - Double input mode, high data rate, 24-bit mode 15934009bffSJacopo Mondi * - Latch input data on PCLKIN rising edge 16034009bffSJacopo Mondi * - Enable HS/VS encoding 16134009bffSJacopo Mondi * - 1-bit parity error detection 16234009bffSJacopo Mondi * 16334009bffSJacopo Mondi * TODO: Make the GMSL link configuration parametric. 16434009bffSJacopo Mondi */ 16534009bffSJacopo Mondi max9271_write(dev, 0x07, MAX9271_DBL | MAX9271_HVEN | 16634009bffSJacopo Mondi MAX9271_EDC_1BIT_PARITY); 16734009bffSJacopo Mondi usleep_range(5000, 8000); 16834009bffSJacopo Mondi 16934009bffSJacopo Mondi /* 17034009bffSJacopo Mondi * Adjust spread spectrum to +4% and auto-detect pixel clock 17134009bffSJacopo Mondi * and serial link rate. 17234009bffSJacopo Mondi */ 17334009bffSJacopo Mondi max9271_write(dev, 0x02, MAX9271_SPREAD_SPECT_4 | MAX9271_R02_RES | 17434009bffSJacopo Mondi MAX9271_PCLK_AUTODETECT | MAX9271_SERIAL_AUTODETECT); 17534009bffSJacopo Mondi usleep_range(5000, 8000); 17634009bffSJacopo Mondi 17734009bffSJacopo Mondi return 0; 17834009bffSJacopo Mondi } 17934009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_configure_gmsl_link); 18034009bffSJacopo Mondi 18134009bffSJacopo Mondi int max9271_set_gpios(struct max9271_device *dev, u8 gpio_mask) 18234009bffSJacopo Mondi { 18334009bffSJacopo Mondi int ret; 18434009bffSJacopo Mondi 18534009bffSJacopo Mondi ret = max9271_read(dev, 0x0f); 18634009bffSJacopo Mondi if (ret < 0) 18734009bffSJacopo Mondi return 0; 18834009bffSJacopo Mondi 18934009bffSJacopo Mondi ret |= gpio_mask; 19034009bffSJacopo Mondi ret = max9271_write(dev, 0x0f, ret); 19134009bffSJacopo Mondi if (ret < 0) { 19234009bffSJacopo Mondi dev_err(&dev->client->dev, "Failed to set gpio (%d)\n", ret); 19334009bffSJacopo Mondi return ret; 19434009bffSJacopo Mondi } 19534009bffSJacopo Mondi 19634009bffSJacopo Mondi usleep_range(3500, 5000); 19734009bffSJacopo Mondi 19834009bffSJacopo Mondi return 0; 19934009bffSJacopo Mondi } 20034009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_set_gpios); 20134009bffSJacopo Mondi 20234009bffSJacopo Mondi int max9271_clear_gpios(struct max9271_device *dev, u8 gpio_mask) 20334009bffSJacopo Mondi { 20434009bffSJacopo Mondi int ret; 20534009bffSJacopo Mondi 20634009bffSJacopo Mondi ret = max9271_read(dev, 0x0f); 20734009bffSJacopo Mondi if (ret < 0) 20834009bffSJacopo Mondi return 0; 20934009bffSJacopo Mondi 21034009bffSJacopo Mondi ret &= ~gpio_mask; 21134009bffSJacopo Mondi ret = max9271_write(dev, 0x0f, ret); 21234009bffSJacopo Mondi if (ret < 0) { 21334009bffSJacopo Mondi dev_err(&dev->client->dev, "Failed to clear gpio (%d)\n", ret); 21434009bffSJacopo Mondi return ret; 21534009bffSJacopo Mondi } 21634009bffSJacopo Mondi 21734009bffSJacopo Mondi usleep_range(3500, 5000); 21834009bffSJacopo Mondi 21934009bffSJacopo Mondi return 0; 22034009bffSJacopo Mondi } 22134009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_clear_gpios); 22234009bffSJacopo Mondi 22334009bffSJacopo Mondi int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask) 22434009bffSJacopo Mondi { 22534009bffSJacopo Mondi int ret; 22634009bffSJacopo Mondi 227909a0a18SJacopo Mondi ret = max9271_read(dev, 0x0e); 22834009bffSJacopo Mondi if (ret < 0) 22934009bffSJacopo Mondi return 0; 23034009bffSJacopo Mondi 23134009bffSJacopo Mondi /* BIT(0) reserved: GPO is always enabled. */ 232909a0a18SJacopo Mondi ret |= (gpio_mask & ~BIT(0)); 23334009bffSJacopo Mondi ret = max9271_write(dev, 0x0e, ret); 23434009bffSJacopo Mondi if (ret < 0) { 23534009bffSJacopo Mondi dev_err(&dev->client->dev, "Failed to enable gpio (%d)\n", ret); 23634009bffSJacopo Mondi return ret; 23734009bffSJacopo Mondi } 23834009bffSJacopo Mondi 23934009bffSJacopo Mondi usleep_range(3500, 5000); 24034009bffSJacopo Mondi 24134009bffSJacopo Mondi return 0; 24234009bffSJacopo Mondi } 24334009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_enable_gpios); 24434009bffSJacopo Mondi 24534009bffSJacopo Mondi int max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask) 24634009bffSJacopo Mondi { 24734009bffSJacopo Mondi int ret; 24834009bffSJacopo Mondi 249909a0a18SJacopo Mondi ret = max9271_read(dev, 0x0e); 25034009bffSJacopo Mondi if (ret < 0) 25134009bffSJacopo Mondi return 0; 25234009bffSJacopo Mondi 25334009bffSJacopo Mondi /* BIT(0) reserved: GPO cannot be disabled */ 254909a0a18SJacopo Mondi ret &= ~(gpio_mask | BIT(0)); 25534009bffSJacopo Mondi ret = max9271_write(dev, 0x0e, ret); 25634009bffSJacopo Mondi if (ret < 0) { 25734009bffSJacopo Mondi dev_err(&dev->client->dev, "Failed to disable gpio (%d)\n", ret); 25834009bffSJacopo Mondi return ret; 25934009bffSJacopo Mondi } 26034009bffSJacopo Mondi 26134009bffSJacopo Mondi usleep_range(3500, 5000); 26234009bffSJacopo Mondi 26334009bffSJacopo Mondi return 0; 26434009bffSJacopo Mondi } 26534009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_disable_gpios); 26634009bffSJacopo Mondi 26734009bffSJacopo Mondi int max9271_verify_id(struct max9271_device *dev) 26834009bffSJacopo Mondi { 26934009bffSJacopo Mondi int ret; 27034009bffSJacopo Mondi 27134009bffSJacopo Mondi ret = max9271_read(dev, 0x1e); 27234009bffSJacopo Mondi if (ret < 0) { 27334009bffSJacopo Mondi dev_err(&dev->client->dev, "MAX9271 ID read failed (%d)\n", 27434009bffSJacopo Mondi ret); 27534009bffSJacopo Mondi return ret; 27634009bffSJacopo Mondi } 27734009bffSJacopo Mondi 27834009bffSJacopo Mondi if (ret != MAX9271_ID) { 27934009bffSJacopo Mondi dev_err(&dev->client->dev, "MAX9271 ID mismatch (0x%02x)\n", 28034009bffSJacopo Mondi ret); 28134009bffSJacopo Mondi return -ENXIO; 28234009bffSJacopo Mondi } 28334009bffSJacopo Mondi 28434009bffSJacopo Mondi return 0; 28534009bffSJacopo Mondi } 28634009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_verify_id); 28734009bffSJacopo Mondi 28834009bffSJacopo Mondi int max9271_set_address(struct max9271_device *dev, u8 addr) 28934009bffSJacopo Mondi { 29034009bffSJacopo Mondi int ret; 29134009bffSJacopo Mondi 29234009bffSJacopo Mondi ret = max9271_write(dev, 0x00, addr << 1); 29334009bffSJacopo Mondi if (ret < 0) { 29434009bffSJacopo Mondi dev_err(&dev->client->dev, 29534009bffSJacopo Mondi "MAX9271 I2C address change failed (%d)\n", ret); 29634009bffSJacopo Mondi return ret; 29734009bffSJacopo Mondi } 29834009bffSJacopo Mondi usleep_range(3500, 5000); 29934009bffSJacopo Mondi 30034009bffSJacopo Mondi return 0; 30134009bffSJacopo Mondi } 30234009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_set_address); 30334009bffSJacopo Mondi 30434009bffSJacopo Mondi int max9271_set_deserializer_address(struct max9271_device *dev, u8 addr) 30534009bffSJacopo Mondi { 30634009bffSJacopo Mondi int ret; 30734009bffSJacopo Mondi 30834009bffSJacopo Mondi ret = max9271_write(dev, 0x01, addr << 1); 30934009bffSJacopo Mondi if (ret < 0) { 31034009bffSJacopo Mondi dev_err(&dev->client->dev, 31134009bffSJacopo Mondi "MAX9271 deserializer address set failed (%d)\n", ret); 31234009bffSJacopo Mondi return ret; 31334009bffSJacopo Mondi } 31434009bffSJacopo Mondi usleep_range(3500, 5000); 31534009bffSJacopo Mondi 31634009bffSJacopo Mondi return 0; 31734009bffSJacopo Mondi } 31834009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_set_deserializer_address); 31934009bffSJacopo Mondi 32034009bffSJacopo Mondi int max9271_set_translation(struct max9271_device *dev, u8 source, u8 dest) 32134009bffSJacopo Mondi { 32234009bffSJacopo Mondi int ret; 32334009bffSJacopo Mondi 32434009bffSJacopo Mondi ret = max9271_write(dev, 0x09, source << 1); 32534009bffSJacopo Mondi if (ret < 0) { 32634009bffSJacopo Mondi dev_err(&dev->client->dev, 32734009bffSJacopo Mondi "MAX9271 I2C translation setup failed (%d)\n", ret); 32834009bffSJacopo Mondi return ret; 32934009bffSJacopo Mondi } 33034009bffSJacopo Mondi usleep_range(3500, 5000); 33134009bffSJacopo Mondi 33234009bffSJacopo Mondi ret = max9271_write(dev, 0x0a, dest << 1); 33334009bffSJacopo Mondi if (ret < 0) { 33434009bffSJacopo Mondi dev_err(&dev->client->dev, 33534009bffSJacopo Mondi "MAX9271 I2C translation setup failed (%d)\n", ret); 33634009bffSJacopo Mondi return ret; 33734009bffSJacopo Mondi } 33834009bffSJacopo Mondi usleep_range(3500, 5000); 33934009bffSJacopo Mondi 34034009bffSJacopo Mondi return 0; 34134009bffSJacopo Mondi } 34234009bffSJacopo Mondi EXPORT_SYMBOL_GPL(max9271_set_translation); 343*ce79aecfSJacopo Mondi 344*ce79aecfSJacopo Mondi MODULE_DESCRIPTION("Maxim MAX9271 GMSL Serializer"); 345*ce79aecfSJacopo Mondi MODULE_AUTHOR("Jacopo Mondi"); 346*ce79aecfSJacopo Mondi MODULE_LICENSE("GPL v2"); 347