diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-12-03 04:33:07 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-12-03 04:33:07 +0000 |
commit | b74cd21dd67661ec78aa874b0703af9abd95872f (patch) | |
tree | 6f77e03afe8c6d310eb2280c8b85946043c9ec8b /sys | |
parent | 49d2025234edfff3228b41cb00528dc9353ebe13 (diff) |
Turn ahci port start into a callback so sxiahci can do some magic to
setup dma. Modified version of a patch from Edwin Amsler which was
based on changes made in Bitrig by Artturi Alm.
ok dlg@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/armv7/sunxi/sxiahci.c | 50 | ||||
-rw-r--r-- | sys/dev/ic/ahci.c | 9 | ||||
-rw-r--r-- | sys/dev/ic/ahcivar.h | 5 |
3 files changed, 44 insertions, 20 deletions
diff --git a/sys/arch/armv7/sunxi/sxiahci.c b/sys/arch/armv7/sunxi/sxiahci.c index f7dd6c12656..5c46c0c13ff 100644 --- a/sys/arch/armv7/sunxi/sxiahci.c +++ b/sys/arch/armv7/sunxi/sxiahci.c @@ -1,6 +1,7 @@ /* $OpenBSD */ /* * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se> + * Copyright (c) 2013,2014 Artturi Alm * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -44,13 +45,21 @@ #define SXIAHCI_TIMEOUT 0x100000 #define SXIAHCI_PWRPIN 40 +#define SXIAHCI_PREG_DMA 0x70 +#define SXIAHCI_PREG_DMA_MASK (0xff<<8) +#define SXIAHCI_PREG_DMA_INIT (0x44<<8) + void sxiahci_attach(struct device *, struct device *, void *); int sxiahci_detach(struct device *, int); int sxiahci_activate(struct device *, int); +int sxiahci_port_start(struct ahci_port *, int); extern int ahci_intr(void *); extern u_int32_t ahci_read(struct ahci_softc *, bus_size_t); extern void ahci_write(struct ahci_softc *, bus_size_t, u_int32_t); +extern u_int32_t ahci_pread(struct ahci_port *, bus_size_t); +extern void ahci_pwrite(struct ahci_port *, bus_size_t, u_int32_t); +extern int ahci_default_port_start(struct ahci_port *, int); struct sxiahci_softc { struct ahci_softc sc; @@ -75,18 +84,15 @@ sxiahci_attach(struct device *parent, struct device *self, void *args) struct armv7_attach_args *aa = args; struct sxiahci_softc *sxisc = (struct sxiahci_softc *)self; struct ahci_softc *sc = &sxisc->sc; - bus_space_tag_t iot; - bus_space_handle_t ioh; uint32_t timo; - sc->sc_iot = iot = aa->aa_iot; + sc->sc_iot = aa->aa_iot; sc->sc_ios = aa->aa_dev->mem[0].size; sc->sc_dmat = aa->aa_dmat; if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, - aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) + sc->sc_ios, 0, &sc->sc_ioh)) panic("sxiahci_attach: bus_space_map failed!"); - ioh = sc->sc_ioh; /* enable clock */ sxiccmu_enablemodule(CCMU_AHCI); @@ -99,13 +105,13 @@ sxiahci_attach(struct device *parent, struct device *self, void *args) SXISET4(sc, SXIAHCI_PHYCS1, 1 << 19); delay(10); - SXICMS4(sc, SXIAHCI_PHYCS0, 1 << 25, - 1 << 23 | 1 << 24 | 1 << 18 | 1 << 26); + SXICMS4(sc, SXIAHCI_PHYCS0, 7 << 24, + 1 << 23 | 5 << 24 | 1 << 18); delay(10); SXICMS4(sc, SXIAHCI_PHYCS1, - 1 << 16 | 1 << 12 | 1 << 11 | 1 << 8 | 1 << 6, - 1 << 17 | 1 << 10 | 1 << 9 | 1 << 7); + 3 << 16 | 0x1f << 8 | 3 << 6, + 2 << 16 | 0x06 << 8 | 2 << 6); delay(10); SXISET4(sc, SXIAHCI_PHYCS1, 1 << 28 | 1 << 15); @@ -114,18 +120,15 @@ sxiahci_attach(struct device *parent, struct device *self, void *args) SXICLR4(sc, SXIAHCI_PHYCS1, 1 << 19); delay(10); - SXICMS4(sc, SXIAHCI_PHYCS0, 1 << 21 | 1 << 20, 1 << 22); - delay(10); - - SXICMS4(sc, SXIAHCI_PHYCS2, 1 << 7 | 1 << 6, - 1 << 9 | 1 << 8 | 1 << 5); + SXICMS4(sc, SXIAHCI_PHYCS0, 0x07 << 20, 0x03 << 20); + SXICMS4(sc, SXIAHCI_PHYCS2, 0x1f << 5, 0x19 << 5); delay(5000); SXISET4(sc, SXIAHCI_PHYCS0, 1 << 19); delay(20); timo = SXIAHCI_TIMEOUT; - while ((SXIREAD4(sc, SXIAHCI_PHYCS0) >> 28 & 3) != 2 && --timo) + while ((SXIREAD4(sc, SXIAHCI_PHYCS0) >> 28 & 7) != 2 && --timo) delay(10); if (!timo) { printf(": AHCI phy power up failed.\n"); @@ -158,7 +161,8 @@ sxiahci_attach(struct device *parent, struct device *self, void *args) SXIWRITE4(sc, SXIAHCI_PI, 1); SXICLR4(sc, SXIAHCI_CAP, AHCI_REG_CAP_SPM); - sc->sc_flags |= AHCI_F_NO_PMP; /* XXX enough? */ + sc->sc_flags |= AHCI_F_NO_PMP; + sc->sc_port_start = sxiahci_port_start; if (ahci_attach(sc) != 0) { /* error printed by ahci_attach */ goto irq; @@ -193,3 +197,17 @@ sxiahci_activate(struct device *self, int act) return ahci_activate((struct device *)sc, act); } + +int +sxiahci_port_start(struct ahci_port *ap, int fre_only) +{ + u_int32_t r; + + /* Setup DMA */ + r = ahci_pread(ap, SXIAHCI_PREG_DMA); + r &= ~SXIAHCI_PREG_DMA_MASK; + r |= SXIAHCI_PREG_DMA_INIT; /* XXX if fre_only? */ + ahci_pwrite(ap, SXIAHCI_PREG_DMA, r); + + return (ahci_default_port_start(ap, fre_only)); +} diff --git a/sys/dev/ic/ahci.c b/sys/dev/ic/ahci.c index 680dae6f7fb..db893ab3ef1 100644 --- a/sys/dev/ic/ahci.c +++ b/sys/dev/ic/ahci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ahci.c,v 1.16 2014/07/13 23:10:23 deraadt Exp $ */ +/* $OpenBSD: ahci.c,v 1.17 2014/12/03 04:33:06 jsg Exp $ */ /* * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> @@ -75,7 +75,7 @@ int ahci_port_alloc(struct ahci_softc *, u_int); void ahci_port_free(struct ahci_softc *, u_int); int ahci_port_init(struct ahci_softc *, u_int); -int ahci_port_start(struct ahci_port *, int); +int ahci_default_port_start(struct ahci_port *, int); int ahci_port_stop(struct ahci_port *, int); int ahci_port_clo(struct ahci_port *); int ahci_port_softreset(struct ahci_port *); @@ -175,6 +175,9 @@ ahci_attach(struct ahci_softc *sc) u_int32_t pi; int i; + if (sc->sc_port_start == NULL) + sc->sc_port_start = ahci_default_port_start; + if (ahci_init(sc) != 0) { /* error already printed by ahci_init */ goto unmap; @@ -832,7 +835,7 @@ reterr: } int -ahci_port_start(struct ahci_port *ap, int fre_only) +ahci_default_port_start(struct ahci_port *ap, int fre_only) { u_int32_t r; diff --git a/sys/dev/ic/ahcivar.h b/sys/dev/ic/ahcivar.h index c0209ddc7df..dee05adef22 100644 --- a/sys/dev/ic/ahcivar.h +++ b/sys/dev/ic/ahcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ahcivar.h,v 1.8 2014/04/14 04:42:22 dlg Exp $ */ +/* $OpenBSD: ahcivar.h,v 1.9 2014/12/03 04:33:06 jsg Exp $ */ /* * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> @@ -137,9 +137,12 @@ struct ahci_softc { u_int32_t sc_ccc_ports; u_int32_t sc_ccc_ports_cur; #endif + + int (*sc_port_start)(struct ahci_port *, int); }; #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) +#define ahci_port_start(_p, _f) ((_p)->ap_sc->sc_port_start((_p), (_f))) int ahci_attach(struct ahci_softc *); int ahci_detach(struct ahci_softc *, int); |