summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rtc/ds1306.c67
-rw-r--r--drivers/rtc/mc13783-rtc.c43
-rw-r--r--drivers/spi/mpc8xxx_spi.c54
-rw-r--r--drivers/spi/mxc_spi.c88
4 files changed, 191 insertions, 61 deletions
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c
index 1c8ac7f..29854fc 100644
--- a/drivers/rtc/ds1306.c
+++ b/drivers/rtc/ds1306.c
@@ -62,13 +62,6 @@
#define RTC_USER_RAM_BASE 0x20
-/*
- * External table of chip select functions (see the appropriate board
- * support for the actual definition of the table).
- */
-extern spi_chipsel_type spi_chipsel[];
-extern int spi_chipsel_cnt;
-
static unsigned int bin2bcd (unsigned int n);
static unsigned char bcd2bin (unsigned char c);
@@ -305,11 +298,29 @@ void rtc_reset (void)
static unsigned char rtc_read (unsigned char reg);
static void rtc_write (unsigned char reg, unsigned char val);
+static struct spi_slave *slave;
+
/* read clock time from DS1306 and return it in *tmp */
int rtc_get (struct rtc_time *tmp)
{
unsigned char sec, min, hour, mday, wday, mon, year;
+ /*
+ * Assuming Vcc = 2.0V (lowest speed)
+ *
+ * REVISIT: If we add an rtc_init() function we can do this
+ * step just once.
+ */
+ if (!slave) {
+ slave = spi_setup_slave(0, CFG_SPI_RTC_DEVID, 600000,
+ SPI_MODE_3 | SPI_CS_HIGH);
+ if (!slave)
+ return;
+ }
+
+ if (spi_claim_bus(slave))
+ return;
+
sec = rtc_read (RTC_SECONDS);
min = rtc_read (RTC_MINUTES);
hour = rtc_read (RTC_HOURS);
@@ -318,6 +329,8 @@ int rtc_get (struct rtc_time *tmp)
mon = rtc_read (RTC_MONTH);
year = rtc_read (RTC_YEAR);
+ spi_release_bus(slave);
+
debug ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
"hr: %02x min: %02x sec: %02x\n",
year, mon, mday, wday, hour, min, sec);
@@ -360,6 +373,17 @@ int rtc_get (struct rtc_time *tmp)
/* set clock time from *tmp in DS1306 RTC */
void rtc_set (struct rtc_time *tmp)
{
+ /* Assuming Vcc = 2.0V (lowest speed) */
+ if (!slave) {
+ slave = spi_setup_slave(0, CFG_SPI_RTC_DEVID, 600000,
+ SPI_MODE_3 | SPI_CS_HIGH);
+ if (!slave)
+ return;
+ }
+
+ if (spi_claim_bus(slave))
+ return;
+
debug ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
@@ -371,6 +395,8 @@ void rtc_set (struct rtc_time *tmp)
rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday));
rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon));
rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000));
+
+ spi_release_bus(slave);
}
/* ------------------------------------------------------------------------- */
@@ -378,6 +404,17 @@ void rtc_set (struct rtc_time *tmp)
/* reset the DS1306 */
void rtc_reset (void)
{
+ /* Assuming Vcc = 2.0V (lowest speed) */
+ if (!slave) {
+ slave = spi_setup_slave(0, CFG_SPI_RTC_DEVID, 600000,
+ SPI_MODE_3 | SPI_CS_HIGH);
+ if (!slave)
+ return;
+ }
+
+ if (spi_claim_bus(slave))
+ return;
+
/* clear the control register */
rtc_write (RTC_CONTROL, 0x00); /* 1st step: reset WP */
rtc_write (RTC_CONTROL, 0x00); /* 2nd step: reset 1Hz, AIE1, AIE0 */
@@ -391,22 +428,18 @@ void rtc_reset (void)
rtc_write (RTC_HOURS_ALARM1, 0x00);
rtc_write (RTC_DAY_OF_WEEK_ALARM0, 0x00);
rtc_write (RTC_DAY_OF_WEEK_ALARM1, 0x00);
+
+ spi_release_bus(slave);
}
/* ------------------------------------------------------------------------- */
static unsigned char rtc_read (unsigned char reg)
{
- unsigned char dout[2]; /* SPI Output Data Bytes */
- unsigned char din[2]; /* SPI Input Data Bytes */
-
- dout[0] = reg;
+ int ret;
- if (spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din) != 0) {
- return 0;
- } else {
- return din[1];
- }
+ ret = spi_w8r8(slave, reg);
+ return ret < 0 ? 0 : ret;
}
/* ------------------------------------------------------------------------- */
@@ -419,7 +452,7 @@ static void rtc_write (unsigned char reg, unsigned char val)
dout[0] = 0x80 | reg;
dout[1] = val;
- spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din);
+ spi_xfer (slave, 16, dout, din, SPI_XFER_BEGIN | SPI_XFER_END);
}
#endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */
diff --git a/drivers/rtc/mc13783-rtc.c b/drivers/rtc/mc13783-rtc.c
index 35b1b8b..b6e1501 100644
--- a/drivers/rtc/mc13783-rtc.c
+++ b/drivers/rtc/mc13783-rtc.c
@@ -24,34 +24,50 @@
#include <rtc.h>
#include <spi.h>
+static struct spi_slave *slave;
+
int rtc_get(struct rtc_time *rtc)
{
u32 day1, day2, time;
u32 reg;
int err, tim, i = 0;
- spi_select(1, 0, SPI_MODE_2 | SPI_CS_HIGH);
+ if (!slave) {
+ /* FIXME: Verify the max SCK rate */
+ slave = spi_setup_slave(1, 0, 1000000,
+ SPI_MODE_2 | SPI_CS_HIGH);
+ if (!slave)
+ return -1;
+ }
+
+ if (spi_claim_bus(slave))
+ return -1;
do {
reg = 0x2c000000;
- err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day1);
+ err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day1,
+ SPI_XFER_BEGIN | SPI_XFER_END);
if (err)
return err;
reg = 0x28000000;
- err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&time);
+ err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
+ SPI_XFER_BEGIN | SPI_XFER_END);
if (err)
return err;
reg = 0x2c000000;
- err = spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day2);
+ err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day2,
+ SPI_XFER_BEGIN | SPI_XFER_END);
if (err)
return err;
} while (day1 != day2 && i++ < 3);
+ spi_release_bus(slave);
+
tim = day1 * 86400 + time;
to_tm(tim, rtc);
@@ -65,16 +81,31 @@ void rtc_set(struct rtc_time *rtc)
{
u32 time, day, reg;
+ if (!slave) {
+ /* FIXME: Verify the max SCK rate */
+ slave = spi_setup_slave(1, 0, 1000000,
+ SPI_MODE_2 | SPI_CS_HIGH);
+ if (!slave)
+ return;
+ }
+
time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
rtc->tm_hour, rtc->tm_min, rtc->tm_sec);
day = time / 86400;
time %= 86400;
+ if (spi_claim_bus(slave))
+ return;
+
reg = 0x2c000000 | day | 0x80000000;
- spi_xfer(0, 32, (uchar *)&reg, (uchar *)&day);
+ spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day,
+ SPI_XFER_BEGIN | SPI_XFER_END);
reg = 0x28000000 | time | 0x80000000;
- spi_xfer(0, 32, (uchar *)&reg, (uchar *)&time);
+ spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
+ SPI_XFER_BEGIN | SPI_XFER_END);
+
+ spi_release_bus(slave);
}
void rtc_reset(void)
diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c
index 2fe838c..136fb50 100644
--- a/drivers/spi/mpc8xxx_spi.c
+++ b/drivers/spi/mpc8xxx_spi.c
@@ -24,6 +24,7 @@
#include <common.h>
#if defined(CONFIG_MPC8XXX_SPI) && defined(CONFIG_HARD_SPI)
+#include <malloc.h>
#include <spi.h>
#include <asm/mpc8xxx_spi.h>
@@ -37,6 +38,34 @@
#define SPI_TIMEOUT 1000
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct spi_slave *slave;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ slave = malloc(sizeof(struct spi_slave));
+ if (!slave)
+ return NULL;
+
+ slave->bus = bus;
+ slave->cs = cs;
+
+ /*
+ * TODO: Some of the code in spi_init() should probably move
+ * here, or into spi_claim_bus() below.
+ */
+
+ return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
void spi_init(void)
{
volatile spi8xxx_t *spi = &((immap_t *) (CFG_IMMR))->spi;
@@ -53,7 +82,18 @@ void spi_init(void)
spi->com = 0; /* LST bit doesn't do anything, so disregard */
}
-int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
{
volatile spi8xxx_t *spi = &((immap_t *) (CFG_IMMR))->spi;
unsigned int tmpdout, tmpdin, event;
@@ -61,11 +101,11 @@ int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
int tm, isRead = 0;
unsigned char charSize = 32;
- debug("spi_xfer: chipsel %08X dout %08X din %08X bitlen %d\n",
- (int)chipsel, *(uint *) dout, *(uint *) din, bitlen);
+ debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+ slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);
- if (chipsel != NULL)
- (*chipsel) (1); /* select the target chip */
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
spi->event = 0xffffffff; /* Clear all SPI events */
@@ -135,8 +175,8 @@ int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
debug("*** spi_xfer: transfer ended. Value=%08x\n", tmpdin);
}
- if (chipsel != NULL)
- (*chipsel) (0); /* deselect the target chip */
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
return 0;
}
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index c166ec5..5957ada 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -19,6 +19,7 @@
*/
#include <common.h>
+#include <malloc.h>
#include <spi.h>
#include <asm/io.h>
@@ -61,17 +62,18 @@ static unsigned long spi_bases[] = {
0x53f84000,
};
-static unsigned long spi_base;
-
#endif
-spi_chipsel_type spi_chipsel[] = {
- (spi_chipsel_type)0,
- (spi_chipsel_type)1,
- (spi_chipsel_type)2,
- (spi_chipsel_type)3,
+struct mxc_spi_slave {
+ struct spi_slave slave;
+ unsigned long base;
+ u32 ctrl_reg;
};
-int spi_chipsel_cnt = sizeof(spi_chipsel) / sizeof(spi_chipsel[0]);
+
+static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
+{
+ return container_of(slave, struct mxc_spi_slave, slave);
+}
static inline u32 reg_read(unsigned long addr)
{
@@ -83,30 +85,31 @@ static inline void reg_write(unsigned long addr, u32 val)
*(volatile unsigned long*)addr = val;
}
-static u32 spi_xchg_single(u32 data, int bitlen)
+static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen)
{
-
- unsigned int cfg_reg = reg_read(spi_base + MXC_CSPICTRL);
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ unsigned int cfg_reg = reg_read(mxcs->base + MXC_CSPICTRL);
if (MXC_CSPICTRL_BITCOUNT(bitlen - 1) != (cfg_reg & MXC_CSPICTRL_BITCOUNT(31))) {
cfg_reg = (cfg_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
MXC_CSPICTRL_BITCOUNT(bitlen - 1);
- reg_write(spi_base + MXC_CSPICTRL, cfg_reg);
+ reg_write(mxcs->base + MXC_CSPICTRL, cfg_reg);
}
- reg_write(spi_base + MXC_CSPITXDATA, data);
+ reg_write(mxcs->base + MXC_CSPITXDATA, data);
cfg_reg |= MXC_CSPICTRL_XCH;
- reg_write(spi_base + MXC_CSPICTRL, cfg_reg);
+ reg_write(mxcs->base + MXC_CSPICTRL, cfg_reg);
- while (reg_read(spi_base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH)
+ while (reg_read(mxcs->base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH)
;
- return reg_read(spi_base + MXC_CSPIRXDATA);
+ return reg_read(mxcs->base + MXC_CSPIRXDATA);
}
-int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
{
int n_blks = (bitlen + 31) / 32;
u32 *out_l, *in_l;
@@ -117,13 +120,10 @@ int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
return 1;
}
- if (!spi_base)
- spi_select(CONFIG_MXC_SPI_IFACE, (int)chipsel, SPI_MODE_2 | SPI_CS_HIGH);
-
for (i = 0, in_l = (u32 *)din, out_l = (u32 *)dout;
i < n_blks;
i++, in_l++, out_l++, bitlen -= 32)
- *in_l = spi_xchg_single(*out_l, bitlen);
+ *in_l = spi_xchg_single(slave, *out_l, bitlen);
return 0;
}
@@ -132,17 +132,17 @@ void spi_init(void)
{
}
-int spi_select(unsigned int bus, unsigned int dev, unsigned long mode)
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
{
unsigned int ctrl_reg;
+ struct mxc_spi_slave *mxcs;
if (bus >= sizeof(spi_bases) / sizeof(spi_bases[0]) ||
- dev > 3)
- return 1;
-
- spi_base = spi_bases[bus];
+ cs > 3)
+ return NULL;
- ctrl_reg = MXC_CSPICTRL_CHIPSELECT(dev) |
+ ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
MXC_CSPICTRL_BITCOUNT(31) |
MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */
MXC_CSPICTRL_EN |
@@ -155,12 +155,38 @@ int spi_select(unsigned int bus, unsigned int dev, unsigned long mode)
if (mode & SPI_CS_HIGH)
ctrl_reg |= MXC_CSPICTRL_SSPOL;
- reg_write(spi_base + MXC_CSPIRESET, 1);
+ mxcs = malloc(sizeof(struct mxc_spi_slave));
+ if (!mxcs)
+ return NULL;
+
+ mxcs->slave.bus = bus;
+ mxcs->slave.cs = cs;
+ mxcs->base = spi_bases[bus];
+ mxcs->ctrl_reg = ctrl_reg;
+
+ return &mxcs->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+
+ reg_write(mxcs->base + MXC_CSPIRESET, 1);
udelay(1);
- reg_write(spi_base + MXC_CSPICTRL, ctrl_reg);
- reg_write(spi_base + MXC_CSPIPERIOD,
+ reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
+ reg_write(mxcs->base + MXC_CSPIPERIOD,
MXC_CSPIPERIOD_32KHZ);
- reg_write(spi_base + MXC_CSPIINT, 0);
+ reg_write(mxcs->base + MXC_CSPIINT, 0);
return 0;
}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* TODO: Shut the controller down */
+}