cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy-isp1301.c (3869B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * NXP ISP1301 USB transceiver driver
      4 *
      5 * Copyright (C) 2012 Roland Stigge
      6 *
      7 * Author: Roland Stigge <stigge@antcom.de>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/mutex.h>
     12#include <linux/i2c.h>
     13#include <linux/usb/phy.h>
     14#include <linux/usb/isp1301.h>
     15
     16#define DRV_NAME		"isp1301"
     17
     18struct isp1301 {
     19	struct usb_phy		phy;
     20	struct mutex		mutex;
     21
     22	struct i2c_client	*client;
     23};
     24
     25#define phy_to_isp(p)		(container_of((p), struct isp1301, phy))
     26
     27static const struct i2c_device_id isp1301_id[] = {
     28	{ "isp1301", 0 },
     29	{ }
     30};
     31MODULE_DEVICE_TABLE(i2c, isp1301_id);
     32
     33static const struct of_device_id isp1301_of_match[] = {
     34	{.compatible = "nxp,isp1301" },
     35	{ },
     36};
     37MODULE_DEVICE_TABLE(of, isp1301_of_match);
     38
     39static struct i2c_client *isp1301_i2c_client;
     40
     41static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear)
     42{
     43	return i2c_smbus_write_byte_data(isp->client, reg | clear, value);
     44}
     45
     46static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value)
     47{
     48	return __isp1301_write(isp, reg, value, 0);
     49}
     50
     51static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value)
     52{
     53	return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR);
     54}
     55
     56static int isp1301_phy_init(struct usb_phy *phy)
     57{
     58	struct isp1301 *isp = phy_to_isp(phy);
     59
     60	/* Disable transparent UART mode first */
     61	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN);
     62	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG);
     63	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG);
     64	isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0);
     65	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN
     66				| MC2_SPD_SUSP_CTRL));
     67
     68	isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0);
     69	isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0);
     70	isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN
     71				| OTG1_DP_PULLDOWN));
     72	isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP
     73				| OTG1_DP_PULLUP));
     74
     75	/* mask all interrupts */
     76	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0);
     77	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0);
     78	isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0);
     79
     80	return 0;
     81}
     82
     83static int isp1301_phy_set_vbus(struct usb_phy *phy, int on)
     84{
     85	struct isp1301 *isp = phy_to_isp(phy);
     86
     87	if (on)
     88		isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
     89	else
     90		isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
     91
     92	return 0;
     93}
     94
     95static int isp1301_probe(struct i2c_client *client,
     96			 const struct i2c_device_id *i2c_id)
     97{
     98	struct isp1301 *isp;
     99	struct usb_phy *phy;
    100
    101	isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL);
    102	if (!isp)
    103		return -ENOMEM;
    104
    105	isp->client = client;
    106	mutex_init(&isp->mutex);
    107
    108	phy = &isp->phy;
    109	phy->dev = &client->dev;
    110	phy->label = DRV_NAME;
    111	phy->init = isp1301_phy_init;
    112	phy->set_vbus = isp1301_phy_set_vbus;
    113	phy->type = USB_PHY_TYPE_USB2;
    114
    115	i2c_set_clientdata(client, isp);
    116	usb_add_phy_dev(phy);
    117
    118	isp1301_i2c_client = client;
    119
    120	return 0;
    121}
    122
    123static int isp1301_remove(struct i2c_client *client)
    124{
    125	struct isp1301 *isp = i2c_get_clientdata(client);
    126
    127	usb_remove_phy(&isp->phy);
    128	isp1301_i2c_client = NULL;
    129
    130	return 0;
    131}
    132
    133static struct i2c_driver isp1301_driver = {
    134	.driver = {
    135		.name = DRV_NAME,
    136		.of_match_table = isp1301_of_match,
    137	},
    138	.probe = isp1301_probe,
    139	.remove = isp1301_remove,
    140	.id_table = isp1301_id,
    141};
    142
    143module_i2c_driver(isp1301_driver);
    144
    145struct i2c_client *isp1301_get_client(struct device_node *node)
    146{
    147	struct i2c_client *client;
    148
    149	/* reference of ISP1301 I2C node via DT */
    150	client = of_find_i2c_device_by_node(node);
    151	if (client)
    152		return client;
    153
    154	/* non-DT: only one ISP1301 chip supported */
    155	return isp1301_i2c_client;
    156}
    157EXPORT_SYMBOL_GPL(isp1301_get_client);
    158
    159MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
    160MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
    161MODULE_LICENSE("GPL");