svn commit: r345948 - head/sys/dev/iicbus/twsi
Author: manu Date: Fri Apr 5 14:44:23 2019 New Revision: 345948 URL: https://svnweb.freebsd.org/changeset/base/345948 Log: twsi: Add interrupt mode Add the ability to use interrupts for i2c message. We still use polling for early boot i2c transfer (for PMIC for example) but as soon as interrupts are available use them. On Allwinner SoC >A20 is seems that polling mode is broken for some reason, this is now fixed by using interrupt mode. For Allwinner also fix the frequency calculation, the one in the code was for when the APB frequency is at 48Mhz while it is at 24Mhz on most (all?) Allwinner SoCs. We now support both cases. While here add more debug info when it's compiled in. Tested On: A20, H3, A64 MFC after:1 month Modified: head/sys/dev/iicbus/twsi/a10_twsi.c head/sys/dev/iicbus/twsi/twsi.c head/sys/dev/iicbus/twsi/twsi.h Modified: head/sys/dev/iicbus/twsi/a10_twsi.c == --- head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr 5 14:27:48 2019 (r345947) +++ head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr 5 14:44:23 2019 (r345948) @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2016 Emmanuel Vadot - * All rights reserved. + * Copyright (c) 2016-2019 Emmanuel Vadot * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -90,6 +89,7 @@ a10_twsi_attach(device_t dev) struct twsi_softc *sc; clk_t clk; hwreset_t rst; + uint64_t freq; int error; sc = device_get_softc(dev); @@ -124,10 +124,31 @@ a10_twsi_attach(device_t dev) sc->reg_soft_reset = TWI_SRST; /* Setup baud rate params */ - sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2); - sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2); - sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2); + clk_get_freq(clk, &freq); + switch (freq) { + /* +* Formula is +* F0 = FINT / 2 ^ CLK_N +* F1 = F0 / (CLK_M + 1) +* +* Doc says that the output freq is F1/10 but my logic analyzer says otherwise +*/ + case 4800: + sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 1); + sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 1); + sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 1); + break; + case 2400: + sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(5, 2); + sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(5, 2); + sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2); + break; + default: + device_printf(dev, "Non supported frequency\n"); + return (ENXIO); + } + sc->need_ack = true; return (twsi_attach(dev)); } @@ -154,7 +175,7 @@ DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_method static devclass_t a10_twsi_devclass; EARLY_DRIVER_MODULE(a10_twsi, simplebus, a10_twsi_driver, a10_twsi_devclass, -0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); EARLY_DRIVER_MODULE(iicbus, a10_twsi, iicbus_driver, iicbus_devclass, -0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); MODULE_DEPEND(a10_twsi, iicbus, 1, 1, 1); Modified: head/sys/dev/iicbus/twsi/twsi.c == --- head/sys/dev/iicbus/twsi/twsi.c Fri Apr 5 14:27:48 2019 (r345947) +++ head/sys/dev/iicbus/twsi/twsi.c Fri Apr 5 14:44:23 2019 (r345948) @@ -31,7 +31,7 @@ /* * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell - * and Allwinner SoCs. Supports master operation only, and works in polling mode. + * and Allwinner SoCs. Supports master operation only. * * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices". @@ -75,8 +75,11 @@ __FBSDID("$FreeBSD$"); #defineTWSI_STATUS_START 0x08 #defineTWSI_STATUS_RPTD_START 0x10 #defineTWSI_STATUS_ADDR_W_ACK 0x18 +#defineTWSI_STATUS_ADDR_W_NACK 0x20 #defineTWSI_STATUS_DATA_WR_ACK 0x28 +#defineTWSI_STATUS_DATA_WR_NACK0x30 #defineTWSI_STATUS_ADDR_R_ACK 0x40 +#defineTWSI_STATUS_ADDR_R_NACK 0x48 #defineTWSI_STATUS_DATA_RD_ACK 0x50 #defineTWSI_STATUS_DATA_RD_NOACK 0x58 @@ -84,27 +87,32 @@ __FBSDID("$FreeBSD$"); #undef TWSI_DEBUG #ifdef TWSI_DEBUG -#definedebugf(fmt, args...) do { printf("%s(): ", __func__); printf(f
svn commit: r345948 - head/sys/dev/iicbus/twsi
Author: manu Date: Fri Apr 5 14:44:23 2019 New Revision: 345948 URL: https://svnweb.freebsd.org/changeset/base/345948 Log: twsi: Add interrupt mode Add the ability to use interrupts for i2c message. We still use polling for early boot i2c transfer (for PMIC for example) but as soon as interrupts are available use them. On Allwinner SoC >A20 is seems that polling mode is broken for some reason, this is now fixed by using interrupt mode. For Allwinner also fix the frequency calculation, the one in the code was for when the APB frequency is at 48Mhz while it is at 24Mhz on most (all?) Allwinner SoCs. We now support both cases. While here add more debug info when it's compiled in. Tested On: A20, H3, A64 MFC after:1 month Modified: head/sys/dev/iicbus/twsi/a10_twsi.c head/sys/dev/iicbus/twsi/twsi.c head/sys/dev/iicbus/twsi/twsi.h Modified: head/sys/dev/iicbus/twsi/a10_twsi.c == --- head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr 5 14:27:48 2019 (r345947) +++ head/sys/dev/iicbus/twsi/a10_twsi.c Fri Apr 5 14:44:23 2019 (r345948) @@ -1,6 +1,5 @@ /*- - * Copyright (c) 2016 Emmanuel Vadot - * All rights reserved. + * Copyright (c) 2016-2019 Emmanuel Vadot * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -90,6 +89,7 @@ a10_twsi_attach(device_t dev) struct twsi_softc *sc; clk_t clk; hwreset_t rst; + uint64_t freq; int error; sc = device_get_softc(dev); @@ -124,10 +124,31 @@ a10_twsi_attach(device_t dev) sc->reg_soft_reset = TWI_SRST; /* Setup baud rate params */ - sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2); - sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2); - sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2); + clk_get_freq(clk, &freq); + switch (freq) { + /* +* Formula is +* F0 = FINT / 2 ^ CLK_N +* F1 = F0 / (CLK_M + 1) +* +* Doc says that the output freq is F1/10 but my logic analyzer says otherwise +*/ + case 4800: + sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 1); + sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 1); + sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 1); + break; + case 2400: + sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(5, 2); + sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(5, 2); + sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2); + break; + default: + device_printf(dev, "Non supported frequency\n"); + return (ENXIO); + } + sc->need_ack = true; return (twsi_attach(dev)); } @@ -154,7 +175,7 @@ DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_method static devclass_t a10_twsi_devclass; EARLY_DRIVER_MODULE(a10_twsi, simplebus, a10_twsi_driver, a10_twsi_devclass, -0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); EARLY_DRIVER_MODULE(iicbus, a10_twsi, iicbus_driver, iicbus_devclass, -0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); MODULE_DEPEND(a10_twsi, iicbus, 1, 1, 1); Modified: head/sys/dev/iicbus/twsi/twsi.c == --- head/sys/dev/iicbus/twsi/twsi.c Fri Apr 5 14:27:48 2019 (r345947) +++ head/sys/dev/iicbus/twsi/twsi.c Fri Apr 5 14:44:23 2019 (r345948) @@ -31,7 +31,7 @@ /* * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell - * and Allwinner SoCs. Supports master operation only, and works in polling mode. + * and Allwinner SoCs. Supports master operation only. * * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices". @@ -75,8 +75,11 @@ __FBSDID("$FreeBSD$"); #defineTWSI_STATUS_START 0x08 #defineTWSI_STATUS_RPTD_START 0x10 #defineTWSI_STATUS_ADDR_W_ACK 0x18 +#defineTWSI_STATUS_ADDR_W_NACK 0x20 #defineTWSI_STATUS_DATA_WR_ACK 0x28 +#defineTWSI_STATUS_DATA_WR_NACK0x30 #defineTWSI_STATUS_ADDR_R_ACK 0x40 +#defineTWSI_STATUS_ADDR_R_NACK 0x48 #defineTWSI_STATUS_DATA_RD_ACK 0x50 #defineTWSI_STATUS_DATA_RD_NOACK 0x58 @@ -84,27 +87,32 @@ __FBSDID("$FreeBSD$"); #undef TWSI_DEBUG #ifdef TWSI_DEBUG -#definedebugf(fmt, args...) do { printf("%s(): ", __func__); printf(f