allwinner: Add support for P2WI in RSB driver

Push-Pull Two Wire interface is a almost compatible iic like bus used
in sun6i SoC. It's only use is to communicate with the power management IC.

Reviewed by:	jmcneill
MFC after:	1 week
Relnotes:	yes
This commit is contained in:
Emmanuel Vadot 2016-10-24 20:33:42 +00:00
parent 77e9044c47
commit cd2b868b5d
3 changed files with 65 additions and 45 deletions

View File

@ -27,7 +27,7 @@
*/
/*
* Allwinner RSB (Reduced Serial Bus)
* Allwinner RSB (Reduced Serial Bus) and P2WI (Push-Pull Two Wire Interface)
*/
#include <sys/cdefs.h>
@ -92,8 +92,12 @@ __FBSDID("$FreeBSD$");
#define RSB_ADDR_PMIC_SECONDARY 0x745
#define RSB_ADDR_PERIPH_IC 0xe89
#define A31_P2WI 1
#define A23_RSB 2
static struct ofw_compat_data compat_data[] = {
{ "allwinner,sun8i-a23-rsb", 1 },
{ "allwinner,sun6i-a31-p2wi", A31_P2WI },
{ "allwinner,sun8i-a23-rsb", A23_RSB },
{ NULL, 0 }
};
@ -131,6 +135,7 @@ struct rsb_softc {
int busy;
uint32_t status;
uint16_t cur_addr;
int type;
struct iic_msg *msg;
};
@ -270,8 +275,8 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
sc = device_get_softc(dev);
/*
* RSB is not really an I2C or SMBus controller, so there are some
* restrictions imposed by the driver.
* P2WI and RSB are not really I2C or SMBus controllers, so there are
* some restrictions imposed by the driver.
*
* Transfers must contain exactly two messages. The first is always
* a write, containing a single data byte offset. Data will either
@ -284,7 +289,8 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
msgs[0].len != 1 || msgs[1].len > RSB_MAXLEN)
return (EINVAL);
/* The controller can read or write 1, 2, or 4 bytes at a time. */
/* The RSB controller can read or write 1, 2, or 4 bytes at a time. */
if (sc->type == A23_RSB) {
if ((msgs[1].flags & IIC_M_RD) != 0) {
switch (msgs[1].len) {
case 1:
@ -314,6 +320,7 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
return (EINVAL);
}
}
}
RSB_LOCK(sc);
while (sc->busy)
@ -322,6 +329,7 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
sc->status = 0;
/* Select current run-time address if necessary */
if (sc->type == A23_RSB) {
device_addr = msgs[0].slave >> 1;
if (sc->cur_addr != device_addr) {
error = rsb_set_rta(dev, device_addr);
@ -330,6 +338,7 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
sc->cur_addr = device_addr;
sc->status = 0;
}
}
/* Clear interrupt status */
RSB_WRITE(sc, RSB_INTS, RSB_READ(sc, RSB_INTS));
@ -344,7 +353,8 @@ rsb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
RSB_WRITE(sc, RSB_DATA0, data[0]);
}
/* Set command type */
/* Set command type for RSB */
if (sc->type == A23_RSB)
RSB_WRITE(sc, RSB_CMD, cmd);
/* Program data length register and transfer direction */
@ -379,10 +389,17 @@ rsb_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
case A23_RSB:
device_set_desc(dev, "Allwinner RSB");
break;
case A31_P2WI:
device_set_desc(dev, "Allwinner P2WI");
break;
default:
return (ENXIO);
}
return (BUS_PROBE_DEFAULT);
}
@ -395,6 +412,8 @@ rsb_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->mtx, device_get_nameunit(dev), "rsb", MTX_DEF);
sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
if (clk_get_by_ofw_index(dev, 0, 0, &sc->clk) == 0) {
error = clk_enable(sc->clk);
if (error != 0) {

View File

@ -12,7 +12,7 @@ arm/allwinner/a10_mmc.c optional mmc
arm/allwinner/a10_sramc.c standard
arm/allwinner/aw_nmi.c optional intrng
arm/allwinner/aw_if_dwc.c optional dwc
arm/allwinner/aw_rsb.c optional rsb
arm/allwinner/aw_rsb.c optional rsb | p2wi
arm/allwinner/aw_rtc.c standard
arm/allwinner/aw_ts.c standard
arm/allwinner/aw_wdog.c standard

View File

@ -106,7 +106,8 @@ device psci
device iicbus
device iic
device twsi
device rsb
device rsb # Allwinner Reduced Serial Bus
device p2wi # Allwinner Push-Pull Two Wire
device axp209 # AXP209 Power Management Unit
device axp81x # AXP813/818 Power Management Unit
device bcm2835_bsc