aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrendan Higgins <brendanhiggins@google.com>2017-06-20 17:15:16 -0400
committerWolfram Sang <wsa@the-dreams.de>2017-06-23 14:39:38 -0400
commitf9eb91350bb20b3e881bc59158071e14ee4f0326 (patch)
treea1a0cad732d7e7872db577e03516f554a152374e
parentf327c686d3ba44eda79a2d9e02a6a242e0b75787 (diff)
i2c: aspeed: added slave support for Aspeed I2C driver
Added slave support for Aspeed I2C controller. Supports fourteen busses present in AST24XX and AST25XX BMC SoCs by Aspeed. Signed-off-by: Brendan Higgins <brendanhiggins@google.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 55f241f2cfcc..f19348328a71 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -49,6 +49,7 @@
49#define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8) 49#define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
50#define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7) 50#define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
51#define ASPEED_I2CD_M_HIGH_SPEED_EN BIT(6) 51#define ASPEED_I2CD_M_HIGH_SPEED_EN BIT(6)
52#define ASPEED_I2CD_SLAVE_EN BIT(1)
52#define ASPEED_I2CD_MASTER_EN BIT(0) 53#define ASPEED_I2CD_MASTER_EN BIT(0)
53 54
54/* 0x04 : I2CD Clock and AC Timing Control Register #1 */ 55/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
@@ -69,6 +70,7 @@
69 */ 70 */
70#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14) 71#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
71#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13) 72#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
73#define ASPEED_I2CD_INTR_SLAVE_MATCH BIT(7)
72#define ASPEED_I2CD_INTR_SCL_TIMEOUT BIT(6) 74#define ASPEED_I2CD_INTR_SCL_TIMEOUT BIT(6)
73#define ASPEED_I2CD_INTR_ABNORMAL BIT(5) 75#define ASPEED_I2CD_INTR_ABNORMAL BIT(5)
74#define ASPEED_I2CD_INTR_NORMAL_STOP BIT(4) 76#define ASPEED_I2CD_INTR_NORMAL_STOP BIT(4)
@@ -101,6 +103,9 @@
101#define ASPEED_I2CD_M_TX_CMD BIT(1) 103#define ASPEED_I2CD_M_TX_CMD BIT(1)
102#define ASPEED_I2CD_M_START_CMD BIT(0) 104#define ASPEED_I2CD_M_START_CMD BIT(0)
103 105
106/* 0x18 : I2CD Slave Device Address Register */
107#define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0)
108
104enum aspeed_i2c_master_state { 109enum aspeed_i2c_master_state {
105 ASPEED_I2C_MASTER_START, 110 ASPEED_I2C_MASTER_START,
106 ASPEED_I2C_MASTER_TX_FIRST, 111 ASPEED_I2C_MASTER_TX_FIRST,
@@ -111,6 +116,15 @@ enum aspeed_i2c_master_state {
111 ASPEED_I2C_MASTER_INACTIVE, 116 ASPEED_I2C_MASTER_INACTIVE,
112}; 117};
113 118
119enum aspeed_i2c_slave_state {
120 ASPEED_I2C_SLAVE_START,
121 ASPEED_I2C_SLAVE_READ_REQUESTED,
122 ASPEED_I2C_SLAVE_READ_PROCESSED,
123 ASPEED_I2C_SLAVE_WRITE_REQUESTED,
124 ASPEED_I2C_SLAVE_WRITE_RECEIVED,
125 ASPEED_I2C_SLAVE_STOP,
126};
127
114struct aspeed_i2c_bus { 128struct aspeed_i2c_bus {
115 struct i2c_adapter adap; 129 struct i2c_adapter adap;
116 struct device *dev; 130 struct device *dev;
@@ -130,6 +144,10 @@ struct aspeed_i2c_bus {
130 int cmd_err; 144 int cmd_err;
131 /* Protected only by i2c_lock_bus */ 145 /* Protected only by i2c_lock_bus */
132 int master_xfer_result; 146 int master_xfer_result;
147#if IS_ENABLED(CONFIG_I2C_SLAVE)
148 struct i2c_client *slave;
149 enum aspeed_i2c_slave_state slave_state;
150#endif /* CONFIG_I2C_SLAVE */
133}; 151};
134 152
135static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus); 153static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
@@ -202,6 +220,110 @@ reset_out:
202 return aspeed_i2c_reset(bus); 220 return aspeed_i2c_reset(bus);
203} 221}
204 222
223#if IS_ENABLED(CONFIG_I2C_SLAVE)
224static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
225{
226 u32 command, irq_status, status_ack = 0;
227 struct i2c_client *slave = bus->slave;
228 bool irq_handled = true;
229 u8 value;
230
231 spin_lock(&bus->lock);
232 if (!slave) {
233 irq_handled = false;
234 goto out;
235 }
236
237 command = readl(bus->base + ASPEED_I2C_CMD_REG);
238 irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
239
240 /* Slave was requested, restart state machine. */
241 if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
242 status_ack |= ASPEED_I2CD_INTR_SLAVE_MATCH;
243 bus->slave_state = ASPEED_I2C_SLAVE_START;
244 }
245
246 /* Slave is not currently active, irq was for someone else. */
247 if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
248 irq_handled = false;
249 goto out;
250 }
251
252 dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
253 irq_status, command);
254
255 /* Slave was sent something. */
256 if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
257 value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
258 /* Handle address frame. */
259 if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
260 if (value & 0x1)
261 bus->slave_state =
262 ASPEED_I2C_SLAVE_READ_REQUESTED;
263 else
264 bus->slave_state =
265 ASPEED_I2C_SLAVE_WRITE_REQUESTED;
266 }
267 status_ack |= ASPEED_I2CD_INTR_RX_DONE;
268 }
269
270 /* Slave was asked to stop. */
271 if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
272 status_ack |= ASPEED_I2CD_INTR_NORMAL_STOP;
273 bus->slave_state = ASPEED_I2C_SLAVE_STOP;
274 }
275 if (irq_status & ASPEED_I2CD_INTR_TX_NAK) {
276 status_ack |= ASPEED_I2CD_INTR_TX_NAK;
277 bus->slave_state = ASPEED_I2C_SLAVE_STOP;
278 }
279
280 switch (bus->slave_state) {
281 case ASPEED_I2C_SLAVE_READ_REQUESTED:
282 if (irq_status & ASPEED_I2CD_INTR_TX_ACK)
283 dev_err(bus->dev, "Unexpected ACK on read request.\n");
284 bus->slave_state = ASPEED_I2C_SLAVE_READ_PROCESSED;
285
286 i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
287 writel(value, bus->base + ASPEED_I2C_BYTE_BUF_REG);
288 writel(ASPEED_I2CD_S_TX_CMD, bus->base + ASPEED_I2C_CMD_REG);
289 break;
290 case ASPEED_I2C_SLAVE_READ_PROCESSED:
291 status_ack |= ASPEED_I2CD_INTR_TX_ACK;
292 if (!(irq_status & ASPEED_I2CD_INTR_TX_ACK))
293 dev_err(bus->dev,
294 "Expected ACK after processed read.\n");
295 i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value);
296 writel(value, bus->base + ASPEED_I2C_BYTE_BUF_REG);
297 writel(ASPEED_I2CD_S_TX_CMD, bus->base + ASPEED_I2C_CMD_REG);
298 break;
299 case ASPEED_I2C_SLAVE_WRITE_REQUESTED:
300 bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED;
301 i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
302 break;
303 case ASPEED_I2C_SLAVE_WRITE_RECEIVED:
304 i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
305 break;
306 case ASPEED_I2C_SLAVE_STOP:
307 i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
308 break;
309 default:
310 dev_err(bus->dev, "unhandled slave_state: %d\n",
311 bus->slave_state);
312 break;
313 }
314
315 if (status_ack != irq_status)
316 dev_err(bus->dev,
317 "irq handled != irq. expected %x, but was %x\n",
318 irq_status, status_ack);
319 writel(status_ack, bus->base + ASPEED_I2C_INTR_STS_REG);
320
321out:
322 spin_unlock(&bus->lock);
323 return irq_handled;
324}
325#endif /* CONFIG_I2C_SLAVE */
326
205/* precondition: bus.lock has been acquired. */ 327/* precondition: bus.lock has been acquired. */
206static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus) 328static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
207{ 329{
@@ -427,6 +549,13 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
427{ 549{
428 struct aspeed_i2c_bus *bus = dev_id; 550 struct aspeed_i2c_bus *bus = dev_id;
429 551
552#if IS_ENABLED(CONFIG_I2C_SLAVE)
553 if (aspeed_i2c_slave_irq(bus)) {
554 dev_dbg(bus->dev, "irq handled by slave.\n");
555 return IRQ_HANDLED;
556 }
557#endif /* CONFIG_I2C_SLAVE */
558
430 return aspeed_i2c_master_irq(bus) ? IRQ_HANDLED : IRQ_NONE; 559 return aspeed_i2c_master_irq(bus) ? IRQ_HANDLED : IRQ_NONE;
431} 560}
432 561
@@ -474,9 +603,75 @@ static u32 aspeed_i2c_functionality(struct i2c_adapter *adap)
474 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA; 603 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
475} 604}
476 605
606#if IS_ENABLED(CONFIG_I2C_SLAVE)
607/* precondition: bus.lock has been acquired. */
608static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr)
609{
610 u32 addr_reg_val, func_ctrl_reg_val;
611
612 /* Set slave addr. */
613 addr_reg_val = readl(bus->base + ASPEED_I2C_DEV_ADDR_REG);
614 addr_reg_val &= ~ASPEED_I2CD_DEV_ADDR_MASK;
615 addr_reg_val |= slave_addr & ASPEED_I2CD_DEV_ADDR_MASK;
616 writel(addr_reg_val, bus->base + ASPEED_I2C_DEV_ADDR_REG);
617
618 /* Turn on slave mode. */
619 func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
620 func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN;
621 writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
622}
623
624static int aspeed_i2c_reg_slave(struct i2c_client *client)
625{
626 struct aspeed_i2c_bus *bus = i2c_get_adapdata(client->adapter);
627 unsigned long flags;
628
629 spin_lock_irqsave(&bus->lock, flags);
630 if (bus->slave) {
631 spin_unlock_irqrestore(&bus->lock, flags);
632 return -EINVAL;
633 }
634
635 __aspeed_i2c_reg_slave(bus, client->addr);
636
637 bus->slave = client;
638 bus->slave_state = ASPEED_I2C_SLAVE_STOP;
639 spin_unlock_irqrestore(&bus->lock, flags);
640
641 return 0;
642}
643
644static int aspeed_i2c_unreg_slave(struct i2c_client *client)
645{
646 struct aspeed_i2c_bus *bus = i2c_get_adapdata(client->adapter);
647 u32 func_ctrl_reg_val;
648 unsigned long flags;
649
650 spin_lock_irqsave(&bus->lock, flags);
651 if (!bus->slave) {
652 spin_unlock_irqrestore(&bus->lock, flags);
653 return -EINVAL;
654 }
655
656 /* Turn off slave mode. */
657 func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
658 func_ctrl_reg_val &= ~ASPEED_I2CD_SLAVE_EN;
659 writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
660
661 bus->slave = NULL;
662 spin_unlock_irqrestore(&bus->lock, flags);
663
664 return 0;
665}
666#endif /* CONFIG_I2C_SLAVE */
667
477static const struct i2c_algorithm aspeed_i2c_algo = { 668static const struct i2c_algorithm aspeed_i2c_algo = {
478 .master_xfer = aspeed_i2c_master_xfer, 669 .master_xfer = aspeed_i2c_master_xfer,
479 .functionality = aspeed_i2c_functionality, 670 .functionality = aspeed_i2c_functionality,
671#if IS_ENABLED(CONFIG_I2C_SLAVE)
672 .reg_slave = aspeed_i2c_reg_slave,
673 .unreg_slave = aspeed_i2c_unreg_slave,
674#endif /* CONFIG_I2C_SLAVE */
480}; 675};
481 676
482static u32 aspeed_i2c_get_clk_reg_val(u32 divisor) 677static u32 aspeed_i2c_get_clk_reg_val(u32 divisor)
@@ -551,6 +746,12 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
551 writel(readl(bus->base + ASPEED_I2C_FUN_CTRL_REG) | fun_ctrl_reg, 746 writel(readl(bus->base + ASPEED_I2C_FUN_CTRL_REG) | fun_ctrl_reg,
552 bus->base + ASPEED_I2C_FUN_CTRL_REG); 747 bus->base + ASPEED_I2C_FUN_CTRL_REG);
553 748
749#if IS_ENABLED(CONFIG_I2C_SLAVE)
750 /* If slave has already been registered, re-enable it. */
751 if (bus->slave)
752 __aspeed_i2c_reg_slave(bus, bus->slave->addr);
753#endif /* CONFIG_I2C_SLAVE */
754
554 /* Set interrupt generation of I2C controller */ 755 /* Set interrupt generation of I2C controller */
555 writel(ASPEED_I2CD_INTR_ALL, bus->base + ASPEED_I2C_INTR_CTRL_REG); 756 writel(ASPEED_I2CD_INTR_ALL, bus->base + ASPEED_I2C_INTR_CTRL_REG);
556 757