Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  4 */
  5
  6#include <linux/clk.h>
  7#include <linux/i2c.h>
  8#include <linux/interrupt.h>
  9#include <linux/io.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12
 13#define UNIPHIER_I2C_DTRM	0x00	/* TX register */
 14#define     UNIPHIER_I2C_DTRM_IRQEN	BIT(11)	/* enable interrupt */
 15#define     UNIPHIER_I2C_DTRM_STA	BIT(10)	/* start condition */
 16#define     UNIPHIER_I2C_DTRM_STO	BIT(9)	/* stop condition */
 17#define     UNIPHIER_I2C_DTRM_NACK	BIT(8)	/* do not return ACK */
 18#define     UNIPHIER_I2C_DTRM_RD	BIT(0)	/* read transaction */
 19#define UNIPHIER_I2C_DREC	0x04	/* RX register */
 20#define     UNIPHIER_I2C_DREC_MST	BIT(14)	/* 1 = controller, 0 = target */
 21#define     UNIPHIER_I2C_DREC_TX	BIT(13)	/* 1 = transmit, 0 = receive */
 22#define     UNIPHIER_I2C_DREC_STS	BIT(12)	/* stop condition detected */
 23#define     UNIPHIER_I2C_DREC_LRB	BIT(11)	/* no ACK */
 24#define     UNIPHIER_I2C_DREC_LAB	BIT(9)	/* arbitration lost */
 25#define     UNIPHIER_I2C_DREC_BBN	BIT(8)	/* bus not busy */
 26#define UNIPHIER_I2C_MYAD	0x08	/* local target address */
 27#define UNIPHIER_I2C_CLK	0x0c	/* clock frequency control */
 28#define UNIPHIER_I2C_BRST	0x10	/* bus reset */
 29#define     UNIPHIER_I2C_BRST_FOEN	BIT(1)	/* normal operation */
 30#define     UNIPHIER_I2C_BRST_RSCL	BIT(0)	/* release SCL */
 31#define UNIPHIER_I2C_HOLD	0x14	/* hold time control */
 32#define UNIPHIER_I2C_BSTS	0x18	/* bus status monitor */
 33#define     UNIPHIER_I2C_BSTS_SDA	BIT(1)	/* readback of SDA line */
 34#define     UNIPHIER_I2C_BSTS_SCL	BIT(0)	/* readback of SCL line */
 35#define UNIPHIER_I2C_NOISE	0x1c	/* noise filter control */
 36#define UNIPHIER_I2C_SETUP	0x20	/* setup time control */
 37
 38struct uniphier_i2c_priv {
 39	struct completion comp;
 40	struct i2c_adapter adap;
 41	void __iomem *membase;
 42	struct clk *clk;
 43	unsigned int busy_cnt;
 44	unsigned int clk_cycle;
 45};
 46
 47static irqreturn_t uniphier_i2c_interrupt(int irq, void *dev_id)
 48{
 49	struct uniphier_i2c_priv *priv = dev_id;
 50
 51	/*
 52	 * This hardware uses edge triggered interrupt.  Do not touch the
 53	 * hardware registers in this handler to make sure to catch the next
 54	 * interrupt edge.  Just send a complete signal and return.
 55	 */
 56	complete(&priv->comp);
 57
 58	return IRQ_HANDLED;
 59}
 60
 61static int uniphier_i2c_xfer_byte(struct i2c_adapter *adap, u32 txdata,
 62				  u32 *rxdatap)
 63{
 64	struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
 65	unsigned long time_left;
 66	u32 rxdata;
 67
 68	reinit_completion(&priv->comp);
 69
 70	txdata |= UNIPHIER_I2C_DTRM_IRQEN;
 71	writel(txdata, priv->membase + UNIPHIER_I2C_DTRM);
 72
 73	time_left = wait_for_completion_timeout(&priv->comp, adap->timeout);
 74	if (unlikely(!time_left))
 75		return -ETIMEDOUT;
 76
 77	rxdata = readl(priv->membase + UNIPHIER_I2C_DREC);
 78	if (rxdatap)
 79		*rxdatap = rxdata;
 80
 81	return 0;
 82}
 83
 84static int uniphier_i2c_send_byte(struct i2c_adapter *adap, u32 txdata)
 85{
 86	u32 rxdata;
 87	int ret;
 88
 89	ret = uniphier_i2c_xfer_byte(adap, txdata, &rxdata);
 90	if (ret)
 91		return ret;
 92
 93	if (unlikely(rxdata & UNIPHIER_I2C_DREC_LAB))
 94		return -EAGAIN;
 95
 96	if (unlikely(rxdata & UNIPHIER_I2C_DREC_LRB))
 97		return -ENXIO;
 98
 99	return 0;
100}
101
102static int uniphier_i2c_tx(struct i2c_adapter *adap, u16 addr, u16 len,
103			   const u8 *buf)
104{
105	int ret;
106
107	ret = uniphier_i2c_send_byte(adap, addr << 1 |
108				     UNIPHIER_I2C_DTRM_STA |
109				     UNIPHIER_I2C_DTRM_NACK);
110	if (ret)
111		return ret;
112
113	while (len--) {
114		ret = uniphier_i2c_send_byte(adap,
115					     UNIPHIER_I2C_DTRM_NACK | *buf++);
116		if (ret)
117			return ret;
118	}
119
120	return 0;
121}
122
123static int uniphier_i2c_rx(struct i2c_adapter *adap, u16 addr, u16 len,
124			   u8 *buf)
125{
126	int ret;
127
128	ret = uniphier_i2c_send_byte(adap, addr << 1 |
129				     UNIPHIER_I2C_DTRM_STA |
130				     UNIPHIER_I2C_DTRM_NACK |
131				     UNIPHIER_I2C_DTRM_RD);
132	if (ret)
133		return ret;
134
135	while (len--) {
136		u32 rxdata;
137
138		ret = uniphier_i2c_xfer_byte(adap,
139					     len ? 0 : UNIPHIER_I2C_DTRM_NACK,
140					     &rxdata);
141		if (ret)
142			return ret;
143		*buf++ = rxdata;
144	}
145
146	return 0;
147}
148
149static int uniphier_i2c_stop(struct i2c_adapter *adap)
150{
151	return uniphier_i2c_send_byte(adap, UNIPHIER_I2C_DTRM_STO |
152				      UNIPHIER_I2C_DTRM_NACK);
153}
154
155static int uniphier_i2c_xfer_one(struct i2c_adapter *adap,
156				 struct i2c_msg *msg, bool stop)
157{
158	bool is_read = msg->flags & I2C_M_RD;
159	bool recovery = false;
160	int ret;
161
162	if (is_read)
163		ret = uniphier_i2c_rx(adap, msg->addr, msg->len, msg->buf);
164	else
165		ret = uniphier_i2c_tx(adap, msg->addr, msg->len, msg->buf);
166
167	if (ret == -EAGAIN) /* could not acquire bus. bail out without STOP */
168		return ret;
169
170	if (ret == -ETIMEDOUT) {
171		/* This error is fatal.  Needs recovery. */
172		stop = false;
173		recovery = true;
174	}
175
176	if (stop) {
177		int ret2 = uniphier_i2c_stop(adap);
178
179		if (ret2) {
180			/* Failed to issue STOP.  The bus needs recovery. */
181			recovery = true;
182			ret = ret ?: ret2;
183		}
184	}
185
186	if (recovery)
187		i2c_recover_bus(adap);
188
189	return ret;
190}
191
192static int uniphier_i2c_check_bus_busy(struct i2c_adapter *adap)
193{
194	struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
195
196	if (!(readl(priv->membase + UNIPHIER_I2C_DREC) &
197						UNIPHIER_I2C_DREC_BBN)) {
198		if (priv->busy_cnt++ > 3) {
199			/*
200			 * If bus busy continues too long, it is probably
201			 * in a wrong state.  Try bus recovery.
202			 */
203			i2c_recover_bus(adap);
204			priv->busy_cnt = 0;
205		}
206
207		return -EAGAIN;
208	}
209
210	priv->busy_cnt = 0;
211	return 0;
212}
213
214static int uniphier_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
215{
216	struct i2c_msg *msg, *emsg = msgs + num;
217	int ret;
218
219	ret = uniphier_i2c_check_bus_busy(adap);
220	if (ret)
221		return ret;
222
223	for (msg = msgs; msg < emsg; msg++) {
224		/* Emit STOP if it is the last message or I2C_M_STOP is set. */
225		bool stop = (msg + 1 == emsg) || (msg->flags & I2C_M_STOP);
226
227		ret = uniphier_i2c_xfer_one(adap, msg, stop);
228		if (ret)
229			return ret;
230	}
231
232	return num;
233}
234
235static u32 uniphier_i2c_functionality(struct i2c_adapter *adap)
236{
237	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
238}
239
240static const struct i2c_algorithm uniphier_i2c_algo = {
241	.xfer = uniphier_i2c_xfer,
242	.functionality = uniphier_i2c_functionality,
243};
244
245static void uniphier_i2c_reset(struct uniphier_i2c_priv *priv, bool reset_on)
246{
247	u32 val = UNIPHIER_I2C_BRST_RSCL;
248
249	val |= reset_on ? 0 : UNIPHIER_I2C_BRST_FOEN;
250	writel(val, priv->membase + UNIPHIER_I2C_BRST);
251}
252
253static int uniphier_i2c_get_scl(struct i2c_adapter *adap)
254{
255	struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
256
257	return !!(readl(priv->membase + UNIPHIER_I2C_BSTS) &
258							UNIPHIER_I2C_BSTS_SCL);
259}
260
261static void uniphier_i2c_set_scl(struct i2c_adapter *adap, int val)
262{
263	struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
264
265	writel(val ? UNIPHIER_I2C_BRST_RSCL : 0,
266	       priv->membase + UNIPHIER_I2C_BRST);
267}
268
269static int uniphier_i2c_get_sda(struct i2c_adapter *adap)
270{
271	struct uniphier_i2c_priv *priv = i2c_get_adapdata(adap);
272
273	return !!(readl(priv->membase + UNIPHIER_I2C_BSTS) &
274							UNIPHIER_I2C_BSTS_SDA);
275}
276
277static void uniphier_i2c_unprepare_recovery(struct i2c_adapter *adap)
278{
279	uniphier_i2c_reset(i2c_get_adapdata(adap), false);
280}
281
282static struct i2c_bus_recovery_info uniphier_i2c_bus_recovery_info = {
283	.recover_bus = i2c_generic_scl_recovery,
284	.get_scl = uniphier_i2c_get_scl,
285	.set_scl = uniphier_i2c_set_scl,
286	.get_sda = uniphier_i2c_get_sda,
287	.unprepare_recovery = uniphier_i2c_unprepare_recovery,
288};
289
290static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv)
291{
292	unsigned int cyc = priv->clk_cycle;
293
294	uniphier_i2c_reset(priv, true);
295
296	/*
297	 * Bit30-16: clock cycles of tLOW.
298	 *  Standard-mode: tLOW = 4.7 us, tHIGH = 4.0 us
299	 *  Fast-mode:     tLOW = 1.3 us, tHIGH = 0.6 us
300	 * "tLow/tHIGH = 5/4" meets both.
301	 */
302	writel((cyc * 5 / 9 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK);
303
304	uniphier_i2c_reset(priv, false);
305}
306
307static int uniphier_i2c_probe(struct platform_device *pdev)
308{
309	struct device *dev = &pdev->dev;
310	struct uniphier_i2c_priv *priv;
311	u32 bus_speed;
312	unsigned long clk_rate;
313	int irq, ret;
314
315	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
316	if (!priv)
317		return -ENOMEM;
318
319	priv->membase = devm_platform_ioremap_resource(pdev, 0);
320	if (IS_ERR(priv->membase))
321		return PTR_ERR(priv->membase);
322
323	irq = platform_get_irq(pdev, 0);
324	if (irq < 0)
325		return irq;
326
327	if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed))
328		bus_speed = I2C_MAX_STANDARD_MODE_FREQ;
329
330	if (!bus_speed || bus_speed > I2C_MAX_FAST_MODE_FREQ) {
331		dev_err(dev, "invalid clock-frequency %d\n", bus_speed);
332		return -EINVAL;
333	}
334
335	priv->clk = devm_clk_get_enabled(dev, NULL);
336	if (IS_ERR(priv->clk)) {
337		dev_err(dev, "failed to enable clock\n");
338		return PTR_ERR(priv->clk);
339	}
340
341	clk_rate = clk_get_rate(priv->clk);
342	if (!clk_rate) {
343		dev_err(dev, "input clock rate should not be zero\n");
344		return -EINVAL;
345	}
346
347	priv->clk_cycle = clk_rate / bus_speed;
348	init_completion(&priv->comp);
349	priv->adap.owner = THIS_MODULE;
350	priv->adap.algo = &uniphier_i2c_algo;
351	priv->adap.dev.parent = dev;
352	priv->adap.dev.of_node = dev->of_node;
353	strscpy(priv->adap.name, "UniPhier I2C", sizeof(priv->adap.name));
354	priv->adap.bus_recovery_info = &uniphier_i2c_bus_recovery_info;
355	i2c_set_adapdata(&priv->adap, priv);
356	platform_set_drvdata(pdev, priv);
357
358	uniphier_i2c_hw_init(priv);
359
360	ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name,
361			       priv);
362	if (ret) {
363		dev_err(dev, "failed to request irq %d\n", irq);
364		return ret;
365	}
366
367	return i2c_add_adapter(&priv->adap);
368}
369
370static void uniphier_i2c_remove(struct platform_device *pdev)
371{
372	struct uniphier_i2c_priv *priv = platform_get_drvdata(pdev);
373
374	i2c_del_adapter(&priv->adap);
375}
376
377static int __maybe_unused uniphier_i2c_suspend(struct device *dev)
378{
379	struct uniphier_i2c_priv *priv = dev_get_drvdata(dev);
380
381	clk_disable_unprepare(priv->clk);
382
383	return 0;
384}
385
386static int __maybe_unused uniphier_i2c_resume(struct device *dev)
387{
388	struct uniphier_i2c_priv *priv = dev_get_drvdata(dev);
389	int ret;
390
391	ret = clk_prepare_enable(priv->clk);
392	if (ret)
393		return ret;
394
395	uniphier_i2c_hw_init(priv);
396
397	return 0;
398}
399
400static const struct dev_pm_ops uniphier_i2c_pm_ops = {
401	SET_SYSTEM_SLEEP_PM_OPS(uniphier_i2c_suspend, uniphier_i2c_resume)
402};
403
404static const struct of_device_id uniphier_i2c_match[] = {
405	{ .compatible = "socionext,uniphier-i2c" },
406	{ /* sentinel */ }
407};
408MODULE_DEVICE_TABLE(of, uniphier_i2c_match);
409
410static struct platform_driver uniphier_i2c_drv = {
411	.probe  = uniphier_i2c_probe,
412	.remove = uniphier_i2c_remove,
413	.driver = {
414		.name  = "uniphier-i2c",
415		.of_match_table = uniphier_i2c_match,
416		.pm = &uniphier_i2c_pm_ops,
417	},
418};
419module_platform_driver(uniphier_i2c_drv);
420
421MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
422MODULE_DESCRIPTION("UniPhier I2C bus driver");
423MODULE_LICENSE("GPL");