summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2014-12-03 04:33:07 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2014-12-03 04:33:07 +0000
commitb74cd21dd67661ec78aa874b0703af9abd95872f (patch)
tree6f77e03afe8c6d310eb2280c8b85946043c9ec8b /sys
parent49d2025234edfff3228b41cb00528dc9353ebe13 (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.c50
-rw-r--r--sys/dev/ic/ahci.c9
-rw-r--r--sys/dev/ic/ahcivar.h5
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);