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

i2c-powermac.c (11644B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3    i2c Support for Apple SMU Controller
      4
      5    Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
      6                       <benh@kernel.crashing.org>
      7
      8
      9*/
     10
     11#include <linux/module.h>
     12#include <linux/kernel.h>
     13#include <linux/types.h>
     14#include <linux/i2c.h>
     15#include <linux/device.h>
     16#include <linux/platform_device.h>
     17#include <linux/of_irq.h>
     18
     19#include <asm/pmac_low_i2c.h>
     20
     21MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
     22MODULE_DESCRIPTION("I2C driver for Apple PowerMac");
     23MODULE_LICENSE("GPL");
     24
     25/*
     26 * SMBUS-type transfer entrypoint
     27 */
     28static s32 i2c_powermac_smbus_xfer(	struct i2c_adapter*	adap,
     29					u16			addr,
     30					unsigned short		flags,
     31					char			read_write,
     32					u8			command,
     33					int			size,
     34					union i2c_smbus_data*	data)
     35{
     36	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
     37	int			rc = 0;
     38	int			read = (read_write == I2C_SMBUS_READ);
     39	int			addrdir = (addr << 1) | read;
     40	int			mode, subsize, len;
     41	u32			subaddr;
     42	u8			*buf;
     43	u8			local[2];
     44
     45	if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
     46		mode = pmac_i2c_mode_std;
     47		subsize = 0;
     48		subaddr = 0;
     49	} else {
     50		mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
     51		subsize = 1;
     52		subaddr = command;
     53	}
     54
     55	switch (size) {
     56        case I2C_SMBUS_QUICK:
     57		buf = NULL;
     58		len = 0;
     59	    	break;
     60        case I2C_SMBUS_BYTE:
     61        case I2C_SMBUS_BYTE_DATA:
     62		buf = &data->byte;
     63		len = 1;
     64	    	break;
     65        case I2C_SMBUS_WORD_DATA:
     66		if (!read) {
     67			local[0] = data->word & 0xff;
     68			local[1] = (data->word >> 8) & 0xff;
     69		}
     70		buf = local;
     71		len = 2;
     72	    	break;
     73
     74	/* Note that these are broken vs. the expected smbus API where
     75	 * on reads, the length is actually returned from the function,
     76	 * but I think the current API makes no sense and I don't want
     77	 * any driver that I haven't verified for correctness to go
     78	 * anywhere near a pmac i2c bus anyway ...
     79	 */
     80        case I2C_SMBUS_BLOCK_DATA:
     81		buf = data->block;
     82		len = data->block[0] + 1;
     83		break;
     84	case I2C_SMBUS_I2C_BLOCK_DATA:
     85		buf = &data->block[1];
     86		len = data->block[0];
     87		break;
     88
     89        default:
     90		return -EINVAL;
     91	}
     92
     93	rc = pmac_i2c_open(bus, 0);
     94	if (rc) {
     95		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
     96		return rc;
     97	}
     98
     99	rc = pmac_i2c_setmode(bus, mode);
    100	if (rc) {
    101		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
    102			mode, rc);
    103		goto bail;
    104	}
    105
    106	rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
    107	if (rc) {
    108		if (rc == -ENXIO)
    109			dev_dbg(&adap->dev,
    110				"I2C transfer at 0x%02x failed, size %d, "
    111				"err %d\n", addrdir >> 1, size, rc);
    112		else
    113			dev_err(&adap->dev,
    114				"I2C transfer at 0x%02x failed, size %d, "
    115				"err %d\n", addrdir >> 1, size, rc);
    116		goto bail;
    117	}
    118
    119	if (size == I2C_SMBUS_WORD_DATA && read) {
    120		data->word = ((u16)local[1]) << 8;
    121		data->word |= local[0];
    122	}
    123
    124 bail:
    125	pmac_i2c_close(bus);
    126	return rc;
    127}
    128
    129/*
    130 * Generic i2c master transfer entrypoint. This driver only support single
    131 * messages (for "lame i2c" transfers). Anything else should use the smbus
    132 * entry point
    133 */
    134static int i2c_powermac_master_xfer(	struct i2c_adapter *adap,
    135					struct i2c_msg *msgs,
    136					int num)
    137{
    138	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
    139	int			rc = 0;
    140	int			addrdir;
    141
    142	if (msgs->flags & I2C_M_TEN)
    143		return -EINVAL;
    144	addrdir = i2c_8bit_addr_from_msg(msgs);
    145
    146	rc = pmac_i2c_open(bus, 0);
    147	if (rc) {
    148		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
    149		return rc;
    150	}
    151	rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
    152	if (rc) {
    153		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
    154			pmac_i2c_mode_std, rc);
    155		goto bail;
    156	}
    157	rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
    158	if (rc < 0) {
    159		if (rc == -ENXIO)
    160			dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
    161				addrdir & 1 ? "read from" : "write to",
    162				addrdir >> 1, rc);
    163		else
    164			dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
    165				addrdir & 1 ? "read from" : "write to",
    166				addrdir >> 1, rc);
    167	}
    168 bail:
    169	pmac_i2c_close(bus);
    170	return rc < 0 ? rc : 1;
    171}
    172
    173static u32 i2c_powermac_func(struct i2c_adapter * adapter)
    174{
    175	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
    176		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
    177		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C;
    178}
    179
    180/* For now, we only handle smbus */
    181static const struct i2c_algorithm i2c_powermac_algorithm = {
    182	.smbus_xfer	= i2c_powermac_smbus_xfer,
    183	.master_xfer	= i2c_powermac_master_xfer,
    184	.functionality	= i2c_powermac_func,
    185};
    186
    187static const struct i2c_adapter_quirks i2c_powermac_quirks = {
    188	.max_num_msgs = 1,
    189};
    190
    191static int i2c_powermac_remove(struct platform_device *dev)
    192{
    193	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
    194
    195	i2c_del_adapter(adapter);
    196	memset(adapter, 0, sizeof(*adapter));
    197
    198	return 0;
    199}
    200
    201static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
    202					   struct pmac_i2c_bus *bus,
    203					   struct device_node *node)
    204{
    205	u32 prop;
    206	int ret;
    207
    208	/* First check for valid "reg" */
    209	ret = of_property_read_u32(node, "reg", &prop);
    210	if (ret == 0)
    211		return (prop & 0xff) >> 1;
    212
    213	/* Then check old-style "i2c-address" */
    214	ret = of_property_read_u32(node, "i2c-address", &prop);
    215	if (ret == 0)
    216		return (prop & 0xff) >> 1;
    217
    218	/* Now handle some devices with missing "reg" properties */
    219	if (of_node_name_eq(node, "cereal"))
    220		return 0x60;
    221	else if (of_node_name_eq(node, "deq"))
    222		return 0x34;
    223
    224	dev_warn(&adap->dev, "No i2c address for %pOF\n", node);
    225
    226	return 0xffffffff;
    227}
    228
    229static void i2c_powermac_create_one(struct i2c_adapter *adap,
    230					      const char *type,
    231					      u32 addr)
    232{
    233	struct i2c_board_info info = {};
    234	struct i2c_client *newdev;
    235
    236	strncpy(info.type, type, sizeof(info.type));
    237	info.addr = addr;
    238	newdev = i2c_new_client_device(adap, &info);
    239	if (IS_ERR(newdev))
    240		dev_err(&adap->dev,
    241			"i2c-powermac: Failure to register missing %s\n",
    242			type);
    243}
    244
    245static void i2c_powermac_add_missing(struct i2c_adapter *adap,
    246					       struct pmac_i2c_bus *bus,
    247					       bool found_onyx)
    248{
    249	struct device_node *busnode = pmac_i2c_get_bus_node(bus);
    250	int rc;
    251
    252	/* Check for the onyx audio codec */
    253#define ONYX_REG_CONTROL		67
    254	if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) {
    255		union i2c_smbus_data data;
    256
    257		rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ,
    258				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
    259				    &data);
    260		if (rc >= 0)
    261			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46);
    262
    263		rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ,
    264				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
    265				    &data);
    266		if (rc >= 0)
    267			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47);
    268	}
    269}
    270
    271static bool i2c_powermac_get_type(struct i2c_adapter *adap,
    272					    struct device_node *node,
    273					    u32 addr, char *type, int type_size)
    274{
    275	char tmp[16];
    276
    277	/*
    278	 * Note: we do _NOT_ want the standard i2c drivers to match with any of
    279	 * our powermac stuff unless they have been specifically modified to
    280	 * handle it on a case by case basis. For example, for thermal control,
    281	 * things like lm75 etc... shall match with their corresponding
    282	 * windfarm drivers, _NOT_ the generic ones, so we force a prefix of
    283	 * 'MAC', onto the modalias to make that happen
    284	 */
    285
    286	/* First try proper modalias */
    287	if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
    288		snprintf(type, type_size, "MAC,%s", tmp);
    289		return true;
    290	}
    291
    292	/* Now look for known workarounds */
    293	if (of_node_name_eq(node, "deq")) {
    294		/* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
    295		if (addr == 0x34) {
    296			snprintf(type, type_size, "MAC,tas3001");
    297			return true;
    298		} else if (addr == 0x35) {
    299			snprintf(type, type_size, "MAC,tas3004");
    300			return true;
    301		}
    302	}
    303
    304	dev_err(&adap->dev, "i2c-powermac: modalias failure on %pOF\n", node);
    305	return false;
    306}
    307
    308static void i2c_powermac_register_devices(struct i2c_adapter *adap,
    309						    struct pmac_i2c_bus *bus)
    310{
    311	struct i2c_client *newdev;
    312	struct device_node *node;
    313	bool found_onyx = false;
    314
    315	/*
    316	 * In some cases we end up with the via-pmu node itself, in this
    317	 * case we skip this function completely as the device-tree will
    318	 * not contain anything useful.
    319	 */
    320	if (of_node_name_eq(adap->dev.of_node, "via-pmu"))
    321		return;
    322
    323	for_each_child_of_node(adap->dev.of_node, node) {
    324		struct i2c_board_info info = {};
    325		u32 addr;
    326
    327		/* Get address & channel */
    328		addr = i2c_powermac_get_addr(adap, bus, node);
    329		if (addr == 0xffffffff)
    330			continue;
    331
    332		/* Multibus setup, check channel */
    333		if (!pmac_i2c_match_adapter(node, adap))
    334			continue;
    335
    336		dev_dbg(&adap->dev, "i2c-powermac: register %pOF\n", node);
    337
    338		/*
    339		 * Keep track of some device existence to handle
    340		 * workarounds later.
    341		 */
    342		if (of_device_is_compatible(node, "pcm3052"))
    343			found_onyx = true;
    344
    345		/* Make up a modalias */
    346		if (!i2c_powermac_get_type(adap, node, addr,
    347					   info.type, sizeof(info.type))) {
    348			continue;
    349		}
    350
    351		/* Fill out the rest of the info structure */
    352		info.addr = addr;
    353		info.irq = irq_of_parse_and_map(node, 0);
    354		info.of_node = of_node_get(node);
    355
    356		newdev = i2c_new_client_device(adap, &info);
    357		if (IS_ERR(newdev)) {
    358			dev_err(&adap->dev, "i2c-powermac: Failure to register"
    359				" %pOF\n", node);
    360			of_node_put(node);
    361			/* We do not dispose of the interrupt mapping on
    362			 * purpose. It's not necessary (interrupt cannot be
    363			 * re-used) and somebody else might have grabbed it
    364			 * via direct DT lookup so let's not bother
    365			 */
    366			continue;
    367		}
    368	}
    369
    370	/* Additional workarounds */
    371	i2c_powermac_add_missing(adap, bus, found_onyx);
    372}
    373
    374static int i2c_powermac_probe(struct platform_device *dev)
    375{
    376	struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev);
    377	struct device_node *parent;
    378	struct i2c_adapter *adapter;
    379	int rc;
    380
    381	if (bus == NULL)
    382		return -EINVAL;
    383	adapter = pmac_i2c_get_adapter(bus);
    384
    385	/* Ok, now we need to make up a name for the interface that will
    386	 * match what we used to do in the past, that is basically the
    387	 * controller's parent device node for keywest. PMU didn't have a
    388	 * naming convention and SMU has a different one
    389	 */
    390	switch(pmac_i2c_get_type(bus)) {
    391	case pmac_i2c_bus_keywest:
    392		parent = of_get_parent(pmac_i2c_get_controller(bus));
    393		if (parent == NULL)
    394			return -EINVAL;
    395		snprintf(adapter->name, sizeof(adapter->name), "%pOFn %d",
    396			 parent,
    397			 pmac_i2c_get_channel(bus));
    398		of_node_put(parent);
    399		break;
    400	case pmac_i2c_bus_pmu:
    401		snprintf(adapter->name, sizeof(adapter->name), "pmu %d",
    402			 pmac_i2c_get_channel(bus));
    403		break;
    404	case pmac_i2c_bus_smu:
    405		/* This is not what we used to do but I'm fixing drivers at
    406		 * the same time as this change
    407		 */
    408		snprintf(adapter->name, sizeof(adapter->name), "smu %d",
    409			 pmac_i2c_get_channel(bus));
    410		break;
    411	default:
    412		return -EINVAL;
    413	}
    414
    415	platform_set_drvdata(dev, adapter);
    416	adapter->algo = &i2c_powermac_algorithm;
    417	adapter->quirks = &i2c_powermac_quirks;
    418	i2c_set_adapdata(adapter, bus);
    419	adapter->dev.parent = &dev->dev;
    420
    421	/* Clear of_node to skip automatic registration of i2c child nodes */
    422	adapter->dev.of_node = NULL;
    423	rc = i2c_add_adapter(adapter);
    424	if (rc) {
    425		printk(KERN_ERR "i2c-powermac: Adapter %s registration "
    426		       "failed\n", adapter->name);
    427		memset(adapter, 0, sizeof(*adapter));
    428		return rc;
    429	}
    430
    431	printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
    432
    433	/* Use custom child registration due to Apple device-tree funkyness */
    434	adapter->dev.of_node = dev->dev.of_node;
    435	i2c_powermac_register_devices(adapter, bus);
    436
    437	return 0;
    438}
    439
    440static struct platform_driver i2c_powermac_driver = {
    441	.probe = i2c_powermac_probe,
    442	.remove = i2c_powermac_remove,
    443	.driver = {
    444		.name = "i2c-powermac",
    445		.bus = &platform_bus_type,
    446	},
    447};
    448
    449module_platform_driver(i2c_powermac_driver);
    450
    451MODULE_ALIAS("platform:i2c-powermac");