On Fri, Dec 15, 2017 at 10:58:22PM +0100, Mark Kettenis wrote:
> Some of the Allwinner SoCs have a so-called Reduces Serial Bus that is
> used to communicate with peripheral chips (mostly power management
> ICs).  The diff below adds a driver for the RSB conntroller, named
> sxirsb(4), and a driver for the RTC component of the X-Powers AC100
> audio codec.  I deliberately cose not to abstract the RSB bus itself
> as that is a unecessary as long as we only have a single RSB
> controller implementation.  But the code is written such that this can
> be easily changed if the need arises.  Shows up in dmesg as:
> 
> sxirsb0 at simplebus0
> "x-powers,axp809" at sxirsb0 addr 0x3a3 not configured
> "x-powers,axp806" at sxirsb0 addr 0x745 not configured
> acrtc0 at sxirsb0 addr 0xe89
> 
> The sxirsb(4) driver attaches early since its children are often used
> for power management.
> 
> ok?
> 

Looks better than what i've had in my branches,
as faking i2c-controller turned out to be messy.
Besides my personal preference not to mention/compare to linux even in
comments , only change i came up w/reading the diff was the obvious typo
in the name Reduces=Reduced.

-Artturi

> 
> Index: arch/armv7/conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v
> retrieving revision 1.99
> diff -u -p -r1.99 GENERIC
> --- arch/armv7/conf/GENERIC   24 Oct 2017 17:00:34 -0000      1.99
> +++ arch/armv7/conf/GENERIC   15 Dec 2017 21:53:54 -0000
> @@ -91,6 +91,8 @@ sxipio*             at fdt? early 1         # GPIO pins fo
>  gpio*                at sxipio?
>  sxiccmu*     at fdt? early 1         # Clock Control Module/Unit
>  sxitimer*    at fdt? early 1
> +sxirsb*              at fdt? early 1         # Reduces Serial Bus

typo here ----------------------------------------^

> +acrtc*               at sxirsb?
>  sxidog*              at fdt?                 # watchdog timer
>  sxirtc*              at fdt?                 # Real Time Clock
>  sxie*                at fdt?
> Index: arch/armv7/conf/RAMDISK
> ===================================================================
> RCS file: /cvs/src/sys/arch/armv7/conf/RAMDISK,v
> retrieving revision 1.92
> diff -u -p -r1.92 RAMDISK
> --- arch/armv7/conf/RAMDISK   24 Oct 2017 17:00:34 -0000      1.92
> +++ arch/armv7/conf/RAMDISK   15 Dec 2017 21:53:54 -0000
> @@ -87,6 +87,8 @@ sxipio*             at fdt? early 1         # GPIO pins fo
>  gpio*                at sxipio?
>  sxiccmu*     at fdt? early 1         # Clock Control Module/Unit
>  sxitimer*    at fdt? early 1
> +sxirsb*              at fdt? early 1         # Reduces Serial Bus

typo here ----------------------------------------^

> +acrtc*               at sxirsb?
>  sxidog*              at fdt?                 # watchdog timer
>  sxirtc*              at fdt?                 # Real Time Clock
>  sxie*                at fdt?
> Index: dev/fdt/acrtc.c
> ===================================================================
> RCS file: dev/fdt/acrtc.c
> diff -N dev/fdt/acrtc.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/fdt/acrtc.c   15 Dec 2017 21:53:55 -0000
> @@ -0,0 +1,186 @@
> +/*   $OpenBSD$       */
> +/*
> + * Copyright (c) 2017 Mark Kettenis <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/device.h>
> +#include <sys/malloc.h>
> +
> +#include <dev/fdt/rsbvar.h>
> +
> +#include <dev/ofw/openfirm.h>
> +#include <dev/ofw/fdt.h>
> +
> +#include <dev/clock_subr.h>
> +
> +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
> +
> +extern todr_chip_handle_t todr_handle;
> +
> +#define RTC_CTRL             0xc7
> +#define  RTC_CTRL_12H_24H_MODE       (1 << 0)
> +#define RTC_SEC                      0xc8
> +#define RTC_MIN                      0xc9
> +#define RTC_HOU                      0xca
> +#define RTC_WEE                      0xcb
> +#define RTC_DAY                      0xcc
> +#define RTC_MON                      0xcd
> +#define RTC_YEA                      0xce
> +#define  RTC_YEA_LEAP_YEAR   (1 << 15)
> +#define RTC_UPD_TRIG         0xcf
> +#define  RTC_UPD_TRIG_UPDATE (1 << 15)
> +
> +struct acrtc_softc {
> +     struct device   sc_dev;
> +     void            *sc_cookie;
> +     uint16_t        sc_rta;
> +
> +     struct todr_chip_handle sc_todr;
> +};
> +
> +int  acrtc_match(struct device *, void *, void *);
> +void acrtc_attach(struct device *, struct device *, void *);
> +
> +struct cfattach acrtc_ca = {
> +     sizeof(struct acrtc_softc), acrtc_match, acrtc_attach
> +};
> +
> +struct cfdriver acrtc_cd = {
> +     NULL, "acrtc", DV_DULL
> +};
> +
> +int  acrtc_clock_read(struct acrtc_softc *, struct clock_ymdhms *);
> +int  acrtc_clock_write(struct acrtc_softc *, struct clock_ymdhms *);
> +int  acrtc_gettime(struct todr_chip_handle *, struct timeval *);
> +int  acrtc_settime(struct todr_chip_handle *, struct timeval *);
> +
> +int
> +acrtc_match(struct device *parent, void *match, void *aux)
> +{
> +     struct rsb_attach_args *ra = aux;
> +
> +     if (strcmp(ra->ra_name, "x-powers,ac100") == 0)
> +             return 1;
> +     return 0;
> +}
> +
> +void
> +acrtc_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct acrtc_softc *sc = (struct acrtc_softc *)self;
> +     struct rsb_attach_args *ra = aux;
> +
> +     sc->sc_cookie = ra->ra_cookie;
> +     sc->sc_rta = ra->ra_rta;
> +
> +     printf("\n");
> +
> +     sc->sc_todr.cookie = sc;
> +     sc->sc_todr.todr_gettime = acrtc_gettime;
> +     sc->sc_todr.todr_settime = acrtc_settime;
> +     todr_handle = &sc->sc_todr;
> +}
> +
> +inline uint16_t
> +acrtc_read_reg(struct acrtc_softc *sc, uint8_t reg)
> +{
> +     return rsb_read_2(sc->sc_cookie, sc->sc_rta, reg);
> +}
> +
> +inline void
> +acrtc_write_reg(struct acrtc_softc *sc, uint8_t reg, uint16_t value)
> +{
> +     rsb_write_2(sc->sc_cookie, sc->sc_rta, reg, value);
> +}
> +
> +int
> +acrtc_gettime(struct todr_chip_handle *handle, struct timeval *tv)
> +{
> +     struct acrtc_softc *sc = handle->cookie;
> +     struct clock_ymdhms dt;
> +     int error;
> +
> +     error = acrtc_clock_read(sc, &dt);
> +     if (error)
> +             return error;
> +
> +     if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
> +         dt.dt_day > 31 || dt.dt_day == 0 ||
> +         dt.dt_mon > 12 || dt.dt_mon == 0 ||
> +         dt.dt_year < POSIX_BASE_YEAR)
> +             return EINVAL;
> +
> +     tv->tv_sec = clock_ymdhms_to_secs(&dt);
> +     tv->tv_usec = 0;
> +     return 0;
> +}
> +
> +int
> +acrtc_settime(struct todr_chip_handle *handle, struct timeval *tv)
> +{
> +     struct acrtc_softc *sc = handle->cookie;
> +     struct clock_ymdhms dt;
> +
> +     clock_secs_to_ymdhms(tv->tv_sec, &dt);
> +
> +     return acrtc_clock_write(sc, &dt);
> +}
> +
> +int
> +acrtc_clock_read(struct acrtc_softc *sc, struct clock_ymdhms *dt)
> +{
> +     uint16_t ctrl;
> +
> +     dt->dt_sec = FROMBCD(acrtc_read_reg(sc, RTC_SEC));
> +     dt->dt_min = FROMBCD(acrtc_read_reg(sc, RTC_MIN));
> +     dt->dt_hour = FROMBCD(acrtc_read_reg(sc, RTC_HOU));
> +     dt->dt_day = FROMBCD(acrtc_read_reg(sc, RTC_DAY));
> +     dt->dt_mon = FROMBCD(acrtc_read_reg(sc, RTC_MON));
> +     dt->dt_year = FROMBCD(acrtc_read_reg(sc, RTC_YEA)) + 2000;
> +
> +#ifdef DEBUG
> +     printf("%02d/%02d/%04d %02d:%02d:%0d\n", dt->dt_day, dt->dt_mon,
> +         dt->dt_year, dt->dt_hour, dt->dt_min, dt->dt_sec);
> +#endif
> +
> +     /* Consider the time to be invalid if the clock is in 12H mode. */
> +     ctrl = acrtc_read_reg(sc, RTC_CTRL);
> +     if ((ctrl & RTC_CTRL_12H_24H_MODE) == 0)
> +             return EINVAL;
> +
> +     return 0;
> +}
> +
> +int
> +acrtc_clock_write(struct acrtc_softc *sc, struct clock_ymdhms *dt)
> +{
> +     uint16_t leap = isleap(dt->dt_year) ? RTC_YEA_LEAP_YEAR : 0;
> +
> +     acrtc_write_reg(sc, RTC_SEC, TOBCD(dt->dt_sec));
> +     acrtc_write_reg(sc, RTC_MIN, TOBCD(dt->dt_min));
> +     acrtc_write_reg(sc, RTC_HOU, TOBCD(dt->dt_hour));
> +     acrtc_write_reg(sc, RTC_WEE, TOBCD(dt->dt_wday));
> +     acrtc_write_reg(sc, RTC_DAY, TOBCD(dt->dt_day));
> +     acrtc_write_reg(sc, RTC_MON, TOBCD(dt->dt_mon));
> +     acrtc_write_reg(sc, RTC_YEA, TOBCD(dt->dt_year - 2000) | leap);
> +     acrtc_write_reg(sc, RTC_UPD_TRIG, RTC_UPD_TRIG_UPDATE);
> +
> +     /* Switch to 24H mode to indicate the time is now valid. */
> +     acrtc_write_reg(sc, RTC_CTRL, RTC_CTRL_12H_24H_MODE);
> +
> +     return 0;
> +}
> Index: dev/fdt/files.fdt
> ===================================================================
> RCS file: /cvs/src/sys/dev/fdt/files.fdt,v
> retrieving revision 1.27
> diff -u -p -r1.27 files.fdt
> --- dev/fdt/files.fdt 21 Sep 2017 12:01:52 -0000      1.27
> +++ dev/fdt/files.fdt 15 Dec 2017 21:53:55 -0000
> @@ -15,6 +15,11 @@ device     sxipio {}: gpiobus
>  attach       sxipio at fdt
>  file dev/fdt/sxipio.c                sxipio
>  
> +define       rsb
> +device       sxirsb {}: rsb
> +attach       sxirsb at fdt
> +file dev/fdt/sxirsb.c                sxirsb
> +
>  device       sxirtc
>  attach       sxirtc at fdt
>  file dev/fdt/sxirtc.c                sxirtc
> @@ -131,3 +136,7 @@ file      dev/fdt/if_mvneta.c             mvneta
>  device       dwxe: ether, ifnet, mii, ifmedia
>  attach       dwxe at fdt
>  file dev/fdt/if_dwxe.c               dwxe
> +
> +device       acrtc
> +attach       acrtc at sxirsb
> +file dev/fdt/acrtc.c                 acrtc
> \ No newline at end of file
> Index: dev/fdt/rsbvar.h
> ===================================================================
> RCS file: dev/fdt/rsbvar.h
> diff -N dev/fdt/rsbvar.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/fdt/rsbvar.h  15 Dec 2017 21:53:55 -0000
> @@ -0,0 +1,29 @@
> +/*   $OpenBSD$       */
> +/*
> + * Copyright (c) 2017 Mark kettenis <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +struct rsb_attach_args {
> +     void            *ra_cookie;
> +     uint16_t        ra_da;
> +     uint8_t         ra_rta;
> +     char            *ra_name;
> +     int             ra_node;
> +};
> +
> +int  rsb_print(void *, const char *);
> +
> +uint16_t rsb_read_2(void *, uint8_t, uint8_t);
> +void rsb_write_2(void *, uint8_t, uint8_t, uint16_t);
> Index: dev/fdt/sxirsb.c
> ===================================================================
> RCS file: dev/fdt/sxirsb.c
> diff -N dev/fdt/sxirsb.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/fdt/sxirsb.c  15 Dec 2017 21:53:55 -0000
> @@ -0,0 +1,302 @@
> +/*   $OpenBSD$       */
> +/*
> + * Copyright (c) 2017 Mark kettenis <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/device.h>
> +
> +#include <machine/bus.h>
> +#include <machine/fdt.h>
> +
> +#include <dev/fdt/rsbvar.h>
> +
> +#include <dev/ofw/openfirm.h>
> +#include <dev/ofw/ofw_clock.h>
> +#include <dev/ofw/ofw_pinctrl.h>
> +#include <dev/ofw/fdt.h>
> +
> +#define RSB_CTRL                     0x0000
> +#define  RSB_CTRL_START_TRANS                (1 << 7)
> +#define  RSB_CTRL_ABORT_TRANS                (1 << 6)
> +#define  RSB_CTRL_GLOBAL_INT_ENB     (1 << 1)
> +#define  RSB_CTRL_SOFT_RESET         (1 << 0)
> +#define RSB_CCR                              0x0004
> +#define  RSB_CCR_CD_ODLY_SHIFT               8
> +#define  RSB_CCR_CD_ODLY_MAX         0x7
> +#define  RSB_CCR_CK_DIV_SHIFT                0
> +#define  RSB_CCR_CK_DIV_MAX          0xff
> +#define RSB_STAT                     0x000c
> +#define  RSB_STAT_TRANS_OVER         (1 << 0)
> +#define RSB_AR                               0x0010
> +#define RSB_DATA                     0x001c
> +#define RSB_DMCR                     0x0028
> +#define  RSB_DMCR_DEVICE_MODE_START  (1U << 31)
> +#define  RSB_DMCR_DEVICE_MODE_DATA   0x7e3e00
> +#define RSB_CMD                              0x002c
> +#define RSB_DAR                              0x0030
> +
> +#define SRTA 0xe8
> +#define RD8  0x8b
> +#define RD16 0x9c
> +#define RD32 0xa6
> +#define WR8  0x4e
> +#define WR16 0x59
> +#define WR32 0x63
> +
> +#define HREAD4(sc, reg)                                                      
> \
> +     (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
> +#define HWRITE4(sc, reg, val)                                                
> \
> +     bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
> +#define HSET4(sc, reg, bits)                                         \
> +     HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
> +#define HCLR4(sc, reg, bits)                                         \
> +     HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
> +
> +struct sxirsb_softc {
> +     struct device           sc_dev;
> +     bus_space_tag_t         sc_iot;
> +     bus_space_handle_t      sc_ioh;
> +
> +     int                     sc_addr;
> +};
> +
> +int  sxirsb_match(struct device *, void *, void *);
> +void sxirsb_attach(struct device *, struct device *, void *);
> +
> +struct cfattach sxirsb_ca = {
> +     sizeof(struct sxirsb_softc), sxirsb_match, sxirsb_attach
> +};
> +
> +struct cfdriver sxirsb_cd = {
> +     NULL, "sxirsb", DV_DULL
> +};
> +
> +uint8_t      sxirsb_rta(uint16_t);
> +
> +int
> +sxirsb_match(struct device *parent, void *match, void *aux)
> +{
> +     struct fdt_attach_args *faa = aux;
> +
> +     return OF_is_compatible(faa->fa_node, "allwinner,sun8i-a23-rsb");
> +}
> +
> +void
> +sxirsb_attach(struct device *parent, struct device *self, void *aux)
> +{
> +     struct sxirsb_softc *sc = (struct sxirsb_softc *)self;
> +     struct fdt_attach_args *faa = aux;
> +     uint32_t freq, parent_freq, div, odly;
> +     struct rsb_attach_args ra;
> +     char name[32];
> +     uint32_t reg;
> +     uint8_t rta;
> +     int node;
> +     int timo;
> +
> +     if (faa->fa_nreg < 1) {
> +             printf(": no registers\n");
> +             return;
> +     }
> +
> +     sc->sc_iot = faa->fa_iot;
> +     if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
> +         faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
> +             printf(": can't map registers\n");
> +             return;
> +     }
> +
> +     pinctrl_byname(faa->fa_node, "default");
> +
> +     clock_enable_all(faa->fa_node);
> +     reset_deassert_all(faa->fa_node);
> +
> +     HWRITE4(sc, RSB_CTRL, RSB_CTRL_SOFT_RESET);
> +     for (timo = 1000; timo > 0; timo--) {
> +             if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_SOFT_RESET) == 0)
> +                     break;
> +             delay(100);
> +     }
> +     if (timo == 0) {
> +             printf(": reset failed\n");
> +             return;
> +     }
> +
> +     freq = OF_getpropint(faa->fa_node, "clock-frequency", 3000000);
> +     parent_freq = clock_get_frequency_idx(faa->fa_node, 0);
> +     div = parent_freq / freq / 2;
> +     if (div == 0)
> +             div = 1;
> +     if (div > (RSB_CCR_CK_DIV_MAX + 1))
> +             div = (RSB_CCR_CK_DIV_MAX + 1);
> +     odly = div >> 1;
> +     if (odly == 0)
> +             odly = 1;
> +     if (odly > RSB_CCR_CD_ODLY_MAX)
> +             odly = RSB_CCR_CD_ODLY_MAX;
> +     HWRITE4(sc, RSB_CCR, (odly << RSB_CCR_CD_ODLY_SHIFT) |
> +         ((div - 1) << RSB_CCR_CK_DIV_SHIFT));
> +
> +     HWRITE4(sc, RSB_DMCR, RSB_DMCR_DEVICE_MODE_START |
> +         RSB_DMCR_DEVICE_MODE_DATA);
> +     for (timo = 1000; timo > 0; timo--) {
> +             if ((HREAD4(sc, RSB_DMCR) & RSB_DMCR_DEVICE_MODE_START) == 0)
> +                     break;
> +             delay(100);
> +     }
> +     if (timo == 0) {
> +             printf(": mode switch failed\n");
> +             return;
> +     }
> +
> +     for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) {
> +             reg = OF_getpropint(node, "reg", 0);
> +             if (reg == 0)
> +                     continue;
> +
> +             rta = sxirsb_rta(reg);
> +             HWRITE4(sc, RSB_CMD, SRTA);
> +             HWRITE4(sc, RSB_DAR, (rta << 16 | reg));
> +
> +             HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS);
> +             for (timo = 1000; timo > 0; timo--) {
> +                     if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0)
> +                             break;
> +                     delay(10);
> +             }
> +             if (timo == 0) {
> +                     printf(": SRTA failed for device 0x%03x\n", reg);
> +                     return;
> +             }
> +     }
> +
> +     printf("\n");
> +
> +     for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) {
> +             reg = OF_getpropint(node, "reg", 0);
> +             if (reg == 0)
> +                     continue;
> +
> +             memset(name, 0, sizeof(name));
> +             if (OF_getprop(node, "compatible", name, sizeof(name)) == -1)
> +                     continue;
> +             if (name[0] == '\0')
> +                     continue;
> +
> +             memset(&ra, 0, sizeof(ra));
> +             ra.ra_cookie = sc;
> +             ra.ra_da = reg;
> +             ra.ra_rta = sxirsb_rta(reg);
> +             ra.ra_name = name;
> +             ra.ra_node = node;
> +             config_found(self, &ra, rsb_print);
> +     }
> +}
> +
> +/*
> + * Use a fixed device address to run-time address mapping.  This keeps
> + * things simple and matches what Linux does.
> + */
> +
> +struct rsb_addr_map {
> +     uint16_t        da;
> +     uint8_t         rta;
> +};
> +
> +struct rsb_addr_map rsb_addr_map[] = {
> +     { 0x3a3, 0x2d },
> +     { 0x745, 0x3a },
> +     { 0xe89, 0x4e }
> +};
> +
> +uint8_t
> +sxirsb_rta(uint16_t da)
> +{
> +     int i;
> +
> +     for (i = 0; i < nitems(rsb_addr_map); i++) {
> +             if (rsb_addr_map[i].da == da)
> +                     return rsb_addr_map[i].rta;
> +     }
> +
> +     return 0;
> +}
> +
> +uint16_t
> +rsb_read_2(void *cookie, uint8_t rta, uint8_t addr)
> +{
> +     struct sxirsb_softc *sc = cookie;
> +     uint16_t stat;
> +     int timo;
> +
> +     HWRITE4(sc, RSB_CMD, RD16);
> +     HWRITE4(sc, RSB_DAR, rta << 16);
> +     HWRITE4(sc, RSB_AR, addr);
> +
> +     HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS);
> +     for (timo = 1000; timo > 0; timo--) {
> +             if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0)
> +                     break;
> +             delay(10);
> +     }
> +     stat = HREAD4(sc, RSB_STAT);
> +     HWRITE4(sc, RSB_STAT, stat);
> +     if (timo == 0 || stat != RSB_STAT_TRANS_OVER) {
> +             printf(": RD16 failed for run-time address 0x%02x\n", rta);
> +             return 0xff;
> +     }
> +
> +     return HREAD4(sc, RSB_DATA);
> +}
> +
> +void
> +rsb_write_2(void *cookie, uint8_t rta, uint8_t addr, uint16_t data)
> +{
> +     struct sxirsb_softc *sc = cookie;
> +     uint16_t stat;
> +     int timo;
> +
> +     HWRITE4(sc, RSB_CMD, WR16);
> +     HWRITE4(sc, RSB_DAR, rta << 16);
> +     HWRITE4(sc, RSB_AR, addr);
> +     HWRITE4(sc, RSB_DATA, data);
> +
> +     HSET4(sc, RSB_CTRL, RSB_CTRL_START_TRANS);
> +     for (timo = 1000; timo > 0; timo--) {
> +             if ((HREAD4(sc, RSB_CTRL) & RSB_CTRL_START_TRANS) == 0)
> +                     break;
> +             delay(10);
> +     }
> +     stat = HREAD4(sc, RSB_STAT);
> +     HWRITE4(sc, RSB_STAT, stat);
> +     if (timo == 0 || stat != RSB_STAT_TRANS_OVER) {
> +             printf(": WR16 failed for run-time address 0x%02x\n", rta);
> +             return;
> +     }
> +}
> +
> +int
> +rsb_print(void *aux, const char *pnp)
> +{
> +     struct rsb_attach_args *ra = aux;
> +
> +     if (pnp != NULL)
> +             printf("\"%s\" at %s", ra->ra_name, pnp);
> +     printf(" addr 0x%x", ra->ra_da);
> +
> +     return (UNCONF);
> +}
> 

Reply via email to