15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 294ae9843SFelipe Balbi /* 394ae9843SFelipe Balbi * NXP ISP1301 USB transceiver driver 494ae9843SFelipe Balbi * 594ae9843SFelipe Balbi * Copyright (C) 2012 Roland Stigge 694ae9843SFelipe Balbi * 794ae9843SFelipe Balbi * Author: Roland Stigge <stigge@antcom.de> 894ae9843SFelipe Balbi */ 994ae9843SFelipe Balbi 1094ae9843SFelipe Balbi #include <linux/module.h> 11790d3a5aSFelipe Balbi #include <linux/mutex.h> 1294ae9843SFelipe Balbi #include <linux/i2c.h> 13790d3a5aSFelipe Balbi #include <linux/usb/phy.h> 14c38a4f3fSFelipe Balbi #include <linux/usb/isp1301.h> 1594ae9843SFelipe Balbi 1694ae9843SFelipe Balbi #define DRV_NAME "isp1301" 1794ae9843SFelipe Balbi 18790d3a5aSFelipe Balbi struct isp1301 { 19790d3a5aSFelipe Balbi struct usb_phy phy; 20790d3a5aSFelipe Balbi struct mutex mutex; 21790d3a5aSFelipe Balbi 22790d3a5aSFelipe Balbi struct i2c_client *client; 23790d3a5aSFelipe Balbi }; 24790d3a5aSFelipe Balbi 25c38a4f3fSFelipe Balbi #define phy_to_isp(p) (container_of((p), struct isp1301, phy)) 26c38a4f3fSFelipe Balbi 2794ae9843SFelipe Balbi static const struct i2c_device_id isp1301_id[] = { 2894ae9843SFelipe Balbi { "isp1301", 0 }, 2994ae9843SFelipe Balbi { } 3094ae9843SFelipe Balbi }; 318fb7ab50SJavier Martinez Canillas MODULE_DEVICE_TABLE(i2c, isp1301_id); 3294ae9843SFelipe Balbi 33fd567653SJavier Martinez Canillas static const struct of_device_id isp1301_of_match[] = { 34fd567653SJavier Martinez Canillas {.compatible = "nxp,isp1301" }, 35fd567653SJavier Martinez Canillas { }, 36fd567653SJavier Martinez Canillas }; 37fd567653SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, isp1301_of_match); 38fd567653SJavier Martinez Canillas 3994ae9843SFelipe Balbi static struct i2c_client *isp1301_i2c_client; 4094ae9843SFelipe Balbi 41c38a4f3fSFelipe Balbi static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear) 42c38a4f3fSFelipe Balbi { 43c38a4f3fSFelipe Balbi return i2c_smbus_write_byte_data(isp->client, reg | clear, value); 44c38a4f3fSFelipe Balbi } 45c38a4f3fSFelipe Balbi 46c38a4f3fSFelipe Balbi static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value) 47c38a4f3fSFelipe Balbi { 48c38a4f3fSFelipe Balbi return __isp1301_write(isp, reg, value, 0); 49c38a4f3fSFelipe Balbi } 50c38a4f3fSFelipe Balbi 51c38a4f3fSFelipe Balbi static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value) 52c38a4f3fSFelipe Balbi { 53c38a4f3fSFelipe Balbi return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR); 54c38a4f3fSFelipe Balbi } 55c38a4f3fSFelipe Balbi 56c38a4f3fSFelipe Balbi static int isp1301_phy_init(struct usb_phy *phy) 57c38a4f3fSFelipe Balbi { 58c38a4f3fSFelipe Balbi struct isp1301 *isp = phy_to_isp(phy); 59c38a4f3fSFelipe Balbi 60c38a4f3fSFelipe Balbi /* Disable transparent UART mode first */ 61c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN); 62c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG); 63c38a4f3fSFelipe Balbi isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG); 64c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0); 65c38a4f3fSFelipe Balbi isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN 66c38a4f3fSFelipe Balbi | MC2_SPD_SUSP_CTRL)); 67c38a4f3fSFelipe Balbi 68c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0); 69c38a4f3fSFelipe Balbi isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0); 70c38a4f3fSFelipe Balbi isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN 71c38a4f3fSFelipe Balbi | OTG1_DP_PULLDOWN)); 72c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP 73c38a4f3fSFelipe Balbi | OTG1_DP_PULLUP)); 74c38a4f3fSFelipe Balbi 75c38a4f3fSFelipe Balbi /* mask all interrupts */ 76c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0); 77c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0); 78c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0); 79c38a4f3fSFelipe Balbi 80c38a4f3fSFelipe Balbi return 0; 81c38a4f3fSFelipe Balbi } 82c38a4f3fSFelipe Balbi 83c38a4f3fSFelipe Balbi static int isp1301_phy_set_vbus(struct usb_phy *phy, int on) 84c38a4f3fSFelipe Balbi { 85c38a4f3fSFelipe Balbi struct isp1301 *isp = phy_to_isp(phy); 86c38a4f3fSFelipe Balbi 87c38a4f3fSFelipe Balbi if (on) 88c38a4f3fSFelipe Balbi isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); 89c38a4f3fSFelipe Balbi else 90c38a4f3fSFelipe Balbi isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); 91c38a4f3fSFelipe Balbi 92c38a4f3fSFelipe Balbi return 0; 93c38a4f3fSFelipe Balbi } 94c38a4f3fSFelipe Balbi 95*9f7cc307SUwe Kleine-König static int isp1301_probe(struct i2c_client *client) 9694ae9843SFelipe Balbi { 97790d3a5aSFelipe Balbi struct isp1301 *isp; 98790d3a5aSFelipe Balbi struct usb_phy *phy; 99790d3a5aSFelipe Balbi 100790d3a5aSFelipe Balbi isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL); 101790d3a5aSFelipe Balbi if (!isp) 102790d3a5aSFelipe Balbi return -ENOMEM; 103790d3a5aSFelipe Balbi 104790d3a5aSFelipe Balbi isp->client = client; 105790d3a5aSFelipe Balbi mutex_init(&isp->mutex); 106790d3a5aSFelipe Balbi 107790d3a5aSFelipe Balbi phy = &isp->phy; 1081abd8b31SRobert Jarzmik phy->dev = &client->dev; 109790d3a5aSFelipe Balbi phy->label = DRV_NAME; 110c38a4f3fSFelipe Balbi phy->init = isp1301_phy_init; 111c38a4f3fSFelipe Balbi phy->set_vbus = isp1301_phy_set_vbus; 112790d3a5aSFelipe Balbi phy->type = USB_PHY_TYPE_USB2; 113790d3a5aSFelipe Balbi 114790d3a5aSFelipe Balbi i2c_set_clientdata(client, isp); 115790d3a5aSFelipe Balbi usb_add_phy_dev(phy); 116790d3a5aSFelipe Balbi 11794ae9843SFelipe Balbi isp1301_i2c_client = client; 118790d3a5aSFelipe Balbi 11994ae9843SFelipe Balbi return 0; 12094ae9843SFelipe Balbi } 12194ae9843SFelipe Balbi 122ed5c2f5fSUwe Kleine-König static void isp1301_remove(struct i2c_client *client) 12394ae9843SFelipe Balbi { 124790d3a5aSFelipe Balbi struct isp1301 *isp = i2c_get_clientdata(client); 125790d3a5aSFelipe Balbi 126790d3a5aSFelipe Balbi usb_remove_phy(&isp->phy); 127790d3a5aSFelipe Balbi isp1301_i2c_client = NULL; 12894ae9843SFelipe Balbi } 12994ae9843SFelipe Balbi 13094ae9843SFelipe Balbi static struct i2c_driver isp1301_driver = { 13194ae9843SFelipe Balbi .driver = { 13294ae9843SFelipe Balbi .name = DRV_NAME, 133a7f12a21SJavier Martinez Canillas .of_match_table = isp1301_of_match, 13494ae9843SFelipe Balbi }, 135*9f7cc307SUwe Kleine-König .probe_new = isp1301_probe, 13694ae9843SFelipe Balbi .remove = isp1301_remove, 13794ae9843SFelipe Balbi .id_table = isp1301_id, 13894ae9843SFelipe Balbi }; 13994ae9843SFelipe Balbi 14094ae9843SFelipe Balbi module_i2c_driver(isp1301_driver); 14194ae9843SFelipe Balbi 14294ae9843SFelipe Balbi struct i2c_client *isp1301_get_client(struct device_node *node) 14394ae9843SFelipe Balbi { 144ca82c067SAndy Shevchenko struct i2c_client *client; 145ca82c067SAndy Shevchenko 146ca82c067SAndy Shevchenko /* reference of ISP1301 I2C node via DT */ 147ca82c067SAndy Shevchenko client = of_find_i2c_device_by_node(node); 148ca82c067SAndy Shevchenko if (client) 149ca82c067SAndy Shevchenko return client; 150ca82c067SAndy Shevchenko 151ca82c067SAndy Shevchenko /* non-DT: only one ISP1301 chip supported */ 15294ae9843SFelipe Balbi return isp1301_i2c_client; 15394ae9843SFelipe Balbi } 15494ae9843SFelipe Balbi EXPORT_SYMBOL_GPL(isp1301_get_client); 15594ae9843SFelipe Balbi 15694ae9843SFelipe Balbi MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); 15794ae9843SFelipe Balbi MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver"); 15894ae9843SFelipe Balbi MODULE_LICENSE("GPL"); 159