// SPDX-License-Identifier: GPL-2.0-or-later /* * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com> * * 2.6 port by Matt Porter <mporter@kernel.crashing.org> * * The documentation describes this as an SMBus controller, but it doesn't * understand any of the SMBus protocol in hardware. It's really an I2C * controller that could emulate most of the SMBus in software. * * This is just a skeleton adapter to use with the Au1550 PSC * algorithm. It was developed for the Pb1550, but will work with * any Au1550 board that has a similar PSC configuration.
*/
/* A read is performed by stuffing the transmit fifo with * zero bytes for timing, waiting for bytes to appear in the * receive fifo, then reading the bytes.
*/
i = 0; while (i < (len - 1)) {
WR(adap, PSC_SMBTXRX, 0); if (wait_for_rx_byte(adap, &buf[i])) return -EIO;
i++;
}
/* The last byte has to indicate transfer done. */
WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP); if (wait_controller_done(adap)) return -EIO;
i = 0; while (i < (len-1)) {
data = buf[i];
WR(adap, PSC_SMBTXRX, data); if (wait_ack(adap)) return -EIO;
i++;
}
/* The last byte has to indicate transfer done. */
data = buf[i];
data |= PSC_SMBTXRX_STP;
WR(adap, PSC_SMBTXRX, data); if (wait_controller_done(adap)) return -EIO; return 0;
}
staticint
au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{ struct i2c_au1550_data *adap = i2c_adap->algo_data; struct i2c_msg *p; int i, err = 0;
WR(adap, PSC_CTRL, PSC_CTRL_ENABLE);
for (i = 0; !err && i < num; i++) {
p = &msgs[i];
err = do_address(adap, p->addr, p->flags & I2C_M_RD,
(p->len == 0)); if (err || !p->len) continue; if (p->flags & I2C_M_RD)
err = i2c_read(adap, p->buf, p->len); else
err = i2c_write(adap, p->buf, p->len);
}
/* Return the number of messages processed, or the error code.
*/ if (err == 0)
err = num;
/* Divide by 8 to get a 6.25 MHz clock. The later protocol * timings are based on this clock.
*/
cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
WR(priv, PSC_SMBCFG, cfg);
WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK);
/* Set the protocol timer values. See Table 71 in the * Au1550 Data Book for standard timing values.
*/
WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(20) | \
PSC_SMBTMR_SET_PU(20) | PSC_SMBTMR_SET_SH(20) | \
PSC_SMBTMR_SET_SU(20) | PSC_SMBTMR_SET_CL(20) | \
PSC_SMBTMR_SET_CH(20));
/* * registering functions to load algorithms at runtime * Prior to calling us, the 50MHz clock frequency and routing * must have been set up for the PSC indicated by the adapter.
*/ staticint
i2c_au1550_probe(struct platform_device *pdev)
{ struct i2c_au1550_data *priv; int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data),
GFP_KERNEL); if (!priv) return -ENOMEM;
priv->psc_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(priv->psc_base)) return PTR_ERR(priv->psc_base);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.