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-au1550.c (8721B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface
      4 * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
      5 *
      6 * 2.6 port by Matt Porter <mporter@kernel.crashing.org>
      7 *
      8 * The documentation describes this as an SMBus controller, but it doesn't
      9 * understand any of the SMBus protocol in hardware.  It's really an I2C
     10 * controller that could emulate most of the SMBus in software.
     11 *
     12 * This is just a skeleton adapter to use with the Au1550 PSC
     13 * algorithm.  It was developed for the Pb1550, but will work with
     14 * any Au1550 board that has a similar PSC configuration.
     15 */
     16
     17#include <linux/delay.h>
     18#include <linux/kernel.h>
     19#include <linux/module.h>
     20#include <linux/platform_device.h>
     21#include <linux/errno.h>
     22#include <linux/i2c.h>
     23#include <linux/slab.h>
     24
     25#include <asm/mach-au1x00/au1000.h>
     26#include <asm/mach-au1x00/au1xxx_psc.h>
     27
     28#define PSC_SEL		0x00
     29#define PSC_CTRL	0x04
     30#define PSC_SMBCFG	0x08
     31#define PSC_SMBMSK	0x0C
     32#define PSC_SMBPCR	0x10
     33#define PSC_SMBSTAT	0x14
     34#define PSC_SMBEVNT	0x18
     35#define PSC_SMBTXRX	0x1C
     36#define PSC_SMBTMR	0x20
     37
     38struct i2c_au1550_data {
     39	void __iomem *psc_base;
     40	int	xfer_timeout;
     41	struct i2c_adapter adap;
     42};
     43
     44static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v)
     45{
     46	__raw_writel(v, a->psc_base + r);
     47	wmb();
     48}
     49
     50static inline unsigned long RD(struct i2c_au1550_data *a, int r)
     51{
     52	return __raw_readl(a->psc_base + r);
     53}
     54
     55static int wait_xfer_done(struct i2c_au1550_data *adap)
     56{
     57	int i;
     58
     59	/* Wait for Tx Buffer Empty */
     60	for (i = 0; i < adap->xfer_timeout; i++) {
     61		if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE)
     62			return 0;
     63
     64		udelay(1);
     65	}
     66
     67	return -ETIMEDOUT;
     68}
     69
     70static int wait_ack(struct i2c_au1550_data *adap)
     71{
     72	unsigned long stat;
     73
     74	if (wait_xfer_done(adap))
     75		return -ETIMEDOUT;
     76
     77	stat = RD(adap, PSC_SMBEVNT);
     78	if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0)
     79		return -ETIMEDOUT;
     80
     81	return 0;
     82}
     83
     84static int wait_master_done(struct i2c_au1550_data *adap)
     85{
     86	int i;
     87
     88	/* Wait for Master Done. */
     89	for (i = 0; i < 2 * adap->xfer_timeout; i++) {
     90		if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0)
     91			return 0;
     92		udelay(1);
     93	}
     94
     95	return -ETIMEDOUT;
     96}
     97
     98static int
     99do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
    100{
    101	unsigned long stat;
    102
    103	/* Reset the FIFOs, clear events. */
    104	stat = RD(adap, PSC_SMBSTAT);
    105	WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR);
    106
    107	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
    108		WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC);
    109		while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0)
    110			cpu_relax();
    111		udelay(50);
    112	}
    113
    114	/* Write out the i2c chip address and specify operation */
    115	addr <<= 1;
    116	if (rd)
    117		addr |= 1;
    118
    119	/* zero-byte xfers stop immediately */
    120	if (q)
    121		addr |= PSC_SMBTXRX_STP;
    122
    123	/* Put byte into fifo, start up master. */
    124	WR(adap, PSC_SMBTXRX, addr);
    125	WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS);
    126	if (wait_ack(adap))
    127		return -EIO;
    128	return (q) ? wait_master_done(adap) : 0;
    129}
    130
    131static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out)
    132{
    133	int j;
    134
    135	if (wait_xfer_done(adap))
    136		return -EIO;
    137
    138	j =  adap->xfer_timeout * 100;
    139	do {
    140		j--;
    141		if (j <= 0)
    142			return -EIO;
    143
    144		if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0)
    145			j = 0;
    146		else
    147			udelay(1);
    148	} while (j > 0);
    149
    150	*out = RD(adap, PSC_SMBTXRX);
    151
    152	return 0;
    153}
    154
    155static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf,
    156		    unsigned int len)
    157{
    158	int i;
    159
    160	if (len == 0)
    161		return 0;
    162
    163	/* A read is performed by stuffing the transmit fifo with
    164	 * zero bytes for timing, waiting for bytes to appear in the
    165	 * receive fifo, then reading the bytes.
    166	 */
    167	i = 0;
    168	while (i < (len - 1)) {
    169		WR(adap, PSC_SMBTXRX, 0);
    170		if (wait_for_rx_byte(adap, &buf[i]))
    171			return -EIO;
    172
    173		i++;
    174	}
    175
    176	/* The last byte has to indicate transfer done. */
    177	WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP);
    178	if (wait_master_done(adap))
    179		return -EIO;
    180
    181	buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff);
    182	return 0;
    183}
    184
    185static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
    186		     unsigned int len)
    187{
    188	int i;
    189	unsigned long data;
    190
    191	if (len == 0)
    192		return 0;
    193
    194	i = 0;
    195	while (i < (len-1)) {
    196		data = buf[i];
    197		WR(adap, PSC_SMBTXRX, data);
    198		if (wait_ack(adap))
    199			return -EIO;
    200		i++;
    201	}
    202
    203	/* The last byte has to indicate transfer done. */
    204	data = buf[i];
    205	data |= PSC_SMBTXRX_STP;
    206	WR(adap, PSC_SMBTXRX, data);
    207	if (wait_master_done(adap))
    208		return -EIO;
    209	return 0;
    210}
    211
    212static int
    213au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
    214{
    215	struct i2c_au1550_data *adap = i2c_adap->algo_data;
    216	struct i2c_msg *p;
    217	int i, err = 0;
    218
    219	WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
    220
    221	for (i = 0; !err && i < num; i++) {
    222		p = &msgs[i];
    223		err = do_address(adap, p->addr, p->flags & I2C_M_RD,
    224				 (p->len == 0));
    225		if (err || !p->len)
    226			continue;
    227		if (p->flags & I2C_M_RD)
    228			err = i2c_read(adap, p->buf, p->len);
    229		else
    230			err = i2c_write(adap, p->buf, p->len);
    231	}
    232
    233	/* Return the number of messages processed, or the error code.
    234	*/
    235	if (err == 0)
    236		err = num;
    237
    238	WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND);
    239
    240	return err;
    241}
    242
    243static u32 au1550_func(struct i2c_adapter *adap)
    244{
    245	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
    246}
    247
    248static const struct i2c_algorithm au1550_algo = {
    249	.master_xfer	= au1550_xfer,
    250	.functionality	= au1550_func,
    251};
    252
    253static void i2c_au1550_setup(struct i2c_au1550_data *priv)
    254{
    255	unsigned long cfg;
    256
    257	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
    258	WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE);
    259	WR(priv, PSC_SMBCFG, 0);
    260	WR(priv, PSC_CTRL, PSC_CTRL_ENABLE);
    261	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
    262		cpu_relax();
    263
    264	cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE;
    265	WR(priv, PSC_SMBCFG, cfg);
    266
    267	/* Divide by 8 to get a 6.25 MHz clock.  The later protocol
    268	 * timings are based on this clock.
    269	 */
    270	cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
    271	WR(priv, PSC_SMBCFG, cfg);
    272	WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
    273
    274	/* Set the protocol timer values.  See Table 71 in the
    275	 * Au1550 Data Book for standard timing values.
    276	 */
    277	WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(20) | \
    278		PSC_SMBTMR_SET_PU(20) | PSC_SMBTMR_SET_SH(20) | \
    279		PSC_SMBTMR_SET_SU(20) | PSC_SMBTMR_SET_CL(20) | \
    280		PSC_SMBTMR_SET_CH(20));
    281
    282	cfg |= PSC_SMBCFG_DE_ENABLE;
    283	WR(priv, PSC_SMBCFG, cfg);
    284	while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0)
    285		cpu_relax();
    286
    287	WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND);
    288}
    289
    290static void i2c_au1550_disable(struct i2c_au1550_data *priv)
    291{
    292	WR(priv, PSC_SMBCFG, 0);
    293	WR(priv, PSC_CTRL, PSC_CTRL_DISABLE);
    294}
    295
    296/*
    297 * registering functions to load algorithms at runtime
    298 * Prior to calling us, the 50MHz clock frequency and routing
    299 * must have been set up for the PSC indicated by the adapter.
    300 */
    301static int
    302i2c_au1550_probe(struct platform_device *pdev)
    303{
    304	struct i2c_au1550_data *priv;
    305	struct resource *r;
    306	int ret;
    307
    308	priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data),
    309			    GFP_KERNEL);
    310	if (!priv)
    311		return -ENOMEM;
    312
    313	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    314	priv->psc_base = devm_ioremap_resource(&pdev->dev, r);
    315	if (IS_ERR(priv->psc_base))
    316		return PTR_ERR(priv->psc_base);
    317
    318	priv->xfer_timeout = 200;
    319
    320	priv->adap.nr = pdev->id;
    321	priv->adap.algo = &au1550_algo;
    322	priv->adap.algo_data = priv;
    323	priv->adap.dev.parent = &pdev->dev;
    324	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
    325
    326	/* Now, set up the PSC for SMBus PIO mode. */
    327	i2c_au1550_setup(priv);
    328
    329	ret = i2c_add_numbered_adapter(&priv->adap);
    330	if (ret) {
    331		i2c_au1550_disable(priv);
    332		return ret;
    333	}
    334
    335	platform_set_drvdata(pdev, priv);
    336	return 0;
    337}
    338
    339static int i2c_au1550_remove(struct platform_device *pdev)
    340{
    341	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
    342
    343	i2c_del_adapter(&priv->adap);
    344	i2c_au1550_disable(priv);
    345	return 0;
    346}
    347
    348#ifdef CONFIG_PM
    349static int i2c_au1550_suspend(struct device *dev)
    350{
    351	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
    352
    353	i2c_au1550_disable(priv);
    354
    355	return 0;
    356}
    357
    358static int i2c_au1550_resume(struct device *dev)
    359{
    360	struct i2c_au1550_data *priv = dev_get_drvdata(dev);
    361
    362	i2c_au1550_setup(priv);
    363
    364	return 0;
    365}
    366
    367static const struct dev_pm_ops i2c_au1550_pmops = {
    368	.suspend	= i2c_au1550_suspend,
    369	.resume		= i2c_au1550_resume,
    370};
    371
    372#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops)
    373
    374#else
    375#define AU1XPSC_SMBUS_PMOPS NULL
    376#endif
    377
    378static struct platform_driver au1xpsc_smbus_driver = {
    379	.driver = {
    380		.name	= "au1xpsc_smbus",
    381		.pm	= AU1XPSC_SMBUS_PMOPS,
    382	},
    383	.probe		= i2c_au1550_probe,
    384	.remove		= i2c_au1550_remove,
    385};
    386
    387module_platform_driver(au1xpsc_smbus_driver);
    388
    389MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
    390MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
    391MODULE_LICENSE("GPL");
    392MODULE_ALIAS("platform:au1xpsc_smbus");