summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-04-11 08:51:27 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-04-11 08:51:27 +0000
commit0b1d7e76d751b9659f4d25be72143cd491704b7e (patch)
tree0197590c2f32ab7927df1360b86c2fff7902d20f
parentf46a7533a4b53de235c8adf78103e9754909ec7d (diff)
downloadrockbox-0b1d7e76d751b9659f4d25be72143cd491704b7e.tar.gz
rockbox-0b1d7e76d751b9659f4d25be72143cd491704b7e.zip
Serial driver for imx31. Perhaps not 100% but maybe 80-90% (future developments will tell). Factor-out the mc13783 stuff and make that driver a layer above the SPI. TODO: start processing PMIC interrupts. Start a clkctl API for imx31 (we'll see if this sticks around but it seems reasonable here). Misc. stuff for convenience/neatness.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17070 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/export/config-gigabeat-s.h3
-rwxr-xr-xfirmware/export/imx31l.h103
-rw-r--r--firmware/export/mc13783.h99
-rw-r--r--firmware/kernel.c3
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c10
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c45
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h86
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c19
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c173
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/spi-imx31.c355
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/spi-imx31.h56
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-target.h3
13 files changed, 864 insertions, 93 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index da7bf37f61..6d32e63be5 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -647,11 +647,13 @@ target/arm/imx31/gigabeat-s/ata-imx31.c
647target/arm/imx31/gigabeat-s/avic-imx31.c 647target/arm/imx31/gigabeat-s/avic-imx31.c
648target/arm/imx31/gigabeat-s/backlight-imx31.c 648target/arm/imx31/gigabeat-s/backlight-imx31.c
649target/arm/imx31/gigabeat-s/button-imx31.c 649target/arm/imx31/gigabeat-s/button-imx31.c
650target/arm/imx31/gigabeat-s/clkctl-imx31.c
650target/arm/imx31/gigabeat-s/dma_start.c 651target/arm/imx31/gigabeat-s/dma_start.c
651target/arm/imx31/gigabeat-s/kernel-imx31.c 652target/arm/imx31/gigabeat-s/kernel-imx31.c
652target/arm/imx31/gigabeat-s/i2c-imx31.c 653target/arm/imx31/gigabeat-s/i2c-imx31.c
653target/arm/imx31/gigabeat-s/i2s-imx31.c 654target/arm/imx31/gigabeat-s/i2s-imx31.c
654target/arm/imx31/gigabeat-s/lcd-imx31.c 655target/arm/imx31/gigabeat-s/lcd-imx31.c
656target/arm/imx31/gigabeat-s/mc13783-imx31.c
655target/arm/imx31/gigabeat-s/mmu-imx31.c 657target/arm/imx31/gigabeat-s/mmu-imx31.c
656target/arm/imx31/gigabeat-s/power-imx31.c 658target/arm/imx31/gigabeat-s/power-imx31.c
657target/arm/imx31/gigabeat-s/powermgmt-imx31.c 659target/arm/imx31/gigabeat-s/powermgmt-imx31.c
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h
index 970a882069..09f5e18ecc 100644
--- a/firmware/export/config-gigabeat-s.h
+++ b/firmware/export/config-gigabeat-s.h
@@ -83,6 +83,9 @@
83/* Define this if you want to use coldfire's i2c interface */ 83/* Define this if you want to use coldfire's i2c interface */
84#define CONFIG_I2C I2C_IMX31L 84#define CONFIG_I2C I2C_IMX31L
85 85
86/* Define the bitmask of serial interface modules (CSPI) used */
87#define SPI_MODULE_MASK (USE_CSPI2_MODULE)
88
86/* Type of mobile power - check this out */ 89/* Type of mobile power - check this out */
87#define BATTERY_CAPACITY_DEFAULT 2000 /* default battery capacity */ 90#define BATTERY_CAPACITY_DEFAULT 2000 /* default battery capacity */
88#define BATTERY_CAPACITY_MIN 1500 /* min. capacity selectable */ 91#define BATTERY_CAPACITY_MIN 1500 /* min. capacity selectable */
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h
index 637b89b0ab..7dc2659b33 100755
--- a/firmware/export/imx31l.h
+++ b/firmware/export/imx31l.h
@@ -516,32 +516,41 @@
516#define GPIO3_ISR (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x18)) 516#define GPIO3_ISR (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x18))
517 517
518/* CSPI */ 518/* CSPI */
519#define CSPI_RXDATA1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x00)) 519#define CSPI_RXDATA_I 0x00 /* Offset - 0x00 */
520#define CSPI_TXDATA1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x04)) 520#define CSPI_TXDATA_I 0x01 /* Offset - 0x04 */
521#define CSPI_CONREG1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x08)) 521#define CSPI_CONREG_I 0x02 /* Offset - 0x08 */
522#define CSPI_INTREG1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x0C)) 522#define CSPI_INTREG_I 0x03 /* Offset - 0x0C */
523#define CSPI_DMAREG1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x10)) 523#define CSPI_DMAREG_I 0x04 /* Offset - 0x10 */
524#define CSPI_STATREG1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x14)) 524#define CSPI_STATREG_I 0x05 /* Offset - 0x14 */
525#define CSPI_PERIODREG1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x18)) 525#define CSPI_PERIODREG_I 0x06 /* Offset - 0x18 */
526#define CSPI_TESTREG1 (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x1C0)) 526#define CSPI_TESTREG_I 0x70 /* Offset - 0x1C0 */
527 527
528#define CSPI_RXDATA2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x00)) 528#define CSPI_RXDATA1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_RXDATA_I])
529#define CSPI_TXDATA2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x04)) 529#define CSPI_TXDATA1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_TXDATA_I])
530#define CSPI_CONREG2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x08)) 530#define CSPI_CONREG1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_CONREG_I])
531#define CSPI_INTREG2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x0C)) 531#define CSPI_INTREG1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_INTREG_I])
532#define CSPI_DMAREG2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x10)) 532#define CSPI_DMAREG1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_DMAREG_I])
533#define CSPI_STATREG2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x14)) 533#define CSPI_STATREG1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_STATREG_I])
534#define CSPI_PERIODREG2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x18)) 534#define CSPI_PERIODREG1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_PERIODREG_I])
535#define CSPI_TESTREG2 (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x1C0)) 535#define CSPI_TESTREG1 (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_TESTREG_I])
536 536
537#define CSPI_RXDATA3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x00)) 537#define CSPI_RXDATA2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_RXDATA_I])
538#define CSPI_TXDATA3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x04)) 538#define CSPI_TXDATA2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_TXDATA_I])
539#define CSPI_CONREG3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x08)) 539#define CSPI_CONREG2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_CONREG_I])
540#define CSPI_INTREG3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x0C)) 540#define CSPI_INTREG2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_INTREG_I])
541#define CSPI_DMAREG3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x10)) 541#define CSPI_DMAREG2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_DMAREG_I])
542#define CSPI_STATREG3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x14)) 542#define CSPI_STATREG2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_STATREG_I])
543#define CSPI_PERIODREG3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x18)) 543#define CSPI_PERIODREG2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_PERIODREG_I])
544#define CSPI_TESTREG3 (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x1C0)) 544#define CSPI_TESTREG2 (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_TESTREG_I])
545
546#define CSPI_RXDATA3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_RXDATA_I])
547#define CSPI_TXDATA3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_TXDATA_I])
548#define CSPI_CONREG3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_CONREG_I])
549#define CSPI_INTREG3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_INTREG_I])
550#define CSPI_DMAREG3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_DMAREG_I])
551#define CSPI_STATREG3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_STATREG_I])
552#define CSPI_PERIODREG3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_PERIODREG_I])
553#define CSPI_TESTREG3 (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_TESTREG_I])
545 554
546/* CSPI CONREG flags/fields */ 555/* CSPI CONREG flags/fields */
547#define CSPI_CONREG_CHIP_SELECT_SS0 (0 << 24) 556#define CSPI_CONREG_CHIP_SELECT_SS0 (0 << 24)
@@ -563,6 +572,7 @@
563#define CSPI_CONREG_DATA_RATE_DIV_256 (6 << 16) 572#define CSPI_CONREG_DATA_RATE_DIV_256 (6 << 16)
564#define CSPI_CONREG_DATA_RATE_DIV_512 (7 << 16) 573#define CSPI_CONREG_DATA_RATE_DIV_512 (7 << 16)
565#define CSPI_CONREG_DATA_RATE_DIV_MASK (7 << 16) 574#define CSPI_CONREG_DATA_RATE_DIV_MASK (7 << 16)
575#define CSPI_BITCOUNT(n) ((n) << 8)
566#define CSPI_CONREG_SSPOL (1 << 7) 576#define CSPI_CONREG_SSPOL (1 << 7)
567#define CSPI_CONREG_SSCTL (1 << 6) 577#define CSPI_CONREG_SSCTL (1 << 6)
568#define CSPI_CONREG_PHA (1 << 6) 578#define CSPI_CONREG_PHA (1 << 6)
@@ -581,7 +591,7 @@
581#define CSPI_INTREG_RREN (1 << 3) 591#define CSPI_INTREG_RREN (1 << 3)
582#define CSPI_INTREG_TFEN (1 << 2) 592#define CSPI_INTREG_TFEN (1 << 2)
583#define CSPI_INTREG_THEN (1 << 1) 593#define CSPI_INTREG_THEN (1 << 1)
584#define CSPI_INTREF_TEEN (1 << 0) 594#define CSPI_INTREG_TEEN (1 << 0)
585 595
586/* CSPI DMAREG flags */ 596/* CSPI DMAREG flags */
587#define CSPI_DMAREG_RFDEN (1 << 5) 597#define CSPI_DMAREG_RFDEN (1 << 5)
@@ -764,12 +774,6 @@
764#define CLKCTL_PMCR1 (*(REG32_PTR_T)(CCM_BASE_ADDR+0x60)) 774#define CLKCTL_PMCR1 (*(REG32_PTR_T)(CCM_BASE_ADDR+0x60))
765#define CLKCTL_PDR2 (*(REG32_PTR_T)(CCM_BASE_ADDR+0x64)) 775#define CLKCTL_PDR2 (*(REG32_PTR_T)(CCM_BASE_ADDR+0x64))
766 776
767#define CG_OFF 0x0 /* Always off */
768#define CG_ON_RUN 0x1 /* On in run mode, off in wait and doze */
769#define CG_ON_RUN_WAIT 0x2 /* On in run and wait modes, off in doze */
770#define CG_ON_ALL 0x3 /* Always on */
771#define CG_MASK 0x3 /* bitmask */
772
773#define CGR0_SD_MMC1(cg) ((cg) << 0*2) 777#define CGR0_SD_MMC1(cg) ((cg) << 0*2)
774#define CGR0_SD_MMC2(cg) ((cg) << 1*2) 778#define CGR0_SD_MMC2(cg) ((cg) << 1*2)
775#define CGR0_GPT(cg) ((cg) << 2*2) 779#define CGR0_GPT(cg) ((cg) << 2*2)
@@ -812,6 +816,39 @@
812#define CGR2_RTIC(cg) ((cg) << 5*2) 816#define CGR2_RTIC(cg) ((cg) << 5*2)
813#define CGR2_FIR(cg) ((cg) << 6*2) 817#define CGR2_FIR(cg) ((cg) << 6*2)
814 818
819#define WIM_GPIO3 (1 << 0)
820#define WIM_GPIO2 (1 << 1)
821#define WIM_GPIO1 (1 << 2)
822#define WIM_PCMCIA (1 << 3)
823#define WIM_WDT (1 << 4)
824#define WIM_USB_OTG (1 << 5)
825#define WIM_IPI_INT_UH2 (1 << 6)
826#define WIM_IPI_INT_UH1 (1 << 7)
827#define WIM_IPI_INT_UART5_ANDED (1 << 8)
828#define WIM_IPI_INT_UART4_ANDED (1 << 9)
829#define WIM_IPI_INT_UART3_ANDED (1 << 10)
830#define WIM_IPI_INT_UART2_ANDED (1 << 11)
831#define WIM_IPI_INT_UART1_ANDED (1 << 12)
832#define WIM_IPI_INT_SIM_DATA_IRQ (1 << 13)
833#define WIM_IPI_INT_SDHC2 (1 << 14)
834#define WIM_IPI_INT_SDHC1 (1 << 15)
835#define WIM_IPI_INT_RTC (1 << 16)
836#define WIM_IPI_INT_PWM (1 << 17)
837#define WIM_IPI_INT_KPP (1 << 18)
838#define WIM_IPI_INT_IIM (1 << 19)
839#define WIM_IPI_INT_GPT (1 << 20)
840#define WIM_IPI_INT_FIR (1 << 21)
841#define WIM_IPI_INT_EPIT2 (1 << 22)
842#define WIM_IPI_INT_EPIT1 (1 << 23)
843#define WIM_IPI_INT_CSPI2 (1 << 24)
844#define WIM_IPI_INT_CSPI1 (1 << 25)
845#define WIM_IPI_INT_POWER_FAIL (1 << 26)
846#define WIM_IPI_INT_CSPI3 (1 << 27)
847#define WIM_RESERVED28 (1 << 28)
848#define WIM_RESERVED29 (1 << 29)
849#define WIM_RESERVED30 (1 << 30)
850#define WIM_RESERVED31 (1 << 31)
851
815/* WEIM - CS0 */ 852/* WEIM - CS0 */
816#define CSCRU 0x00 853#define CSCRU 0x00
817#define CSCRL 0x04 854#define CSCRL 0x04
diff --git a/firmware/export/mc13783.h b/firmware/export/mc13783.h
new file mode 100644
index 0000000000..fe9ff74e33
--- /dev/null
+++ b/firmware/export/mc13783.h
@@ -0,0 +1,99 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef _MC13783_H_
20#define _MC13783_H_
21
22enum mc13783_regs_enum
23{
24 MC13783_INTERRUPT_STATUS0 = 0x00,
25 MC13783_INTERRUPT_MASK0,
26 MC13783_INTERRUPT_SENSE0,
27 MC13783_INTERRUPT_STATUS1,
28 MC13783_INTERRUPT_MASK1,
29 MC13783_INTERRUPT_SENSE1,
30 MC13783_POWER_UP_MODE_SENSE,
31 MC13783_IDENTIFICATION,
32 MC13783_SEMAPHORE,
33 MC13783_ARBITRATION_PERIPHERAL_AUDIO,
34 MC13783_ARBITRATION_SWITCHERS,
35 MC13783_ARBITRATION_REGULATORS0,
36 MC13783_ARBITRATION_REGULATORS1,
37 MC13783_POWER_CONTROL0,
38 MC13783_POWER_CONTROL1,
39 MC13783_POWER_CONTROL2,
40 MC13783_REGEN_ASSIGNMENT,
41 MC13783_CONTROL_SPARE,
42 MC13783_MEMORYA,
43 MC13783_MEMORYB,
44 MC13783_RTC_TIME,
45 MC13783_RTC_ALARM,
46 MC13783_RTC_DAY,
47 MC13783_RTC_DAY_ALARM,
48 MC13783_SWITCHERS0,
49 MC13783_SWITCHERS1,
50 MC13783_SWITCHERS2,
51 MC13783_SWITCHERS3,
52 MC13783_SWITCHERS4,
53 MC13783_SWITCHERS5,
54 MC13783_REGULATOR_SETTING0,
55 MC13783_REGULATOR_SETTING1,
56 MC13783_REGULATOR_MODE0,
57 MC13783_REGULATOR_MODE1,
58 MC13783_POWER_MISCELLANEOUS,
59 MC13783_POWER_SPARE,
60 MC13783_AUDIO_RX0,
61 MC13783_AUDIO_RX1,
62 MC13783_AUDIO_TX,
63 MC13783_SSI_NETWORK,
64 MC13783_AUDIO_CODEC,
65 MC13783_AUDIO_STEREO_CODEC,
66 MC13783_AUDIO_SPARE,
67 MC13783_ADC0,
68 MC13783_ADC1,
69 MC13783_ADC2,
70 MC13783_ADC3,
71 MC13783_ADC4,
72 MC13783_CHARGER,
73 MC13783_USB0,
74 MC13783_CHARGER_USB1,
75 MC13783_LED_CONTROL0,
76 MC13783_LED_CONTROL1,
77 MC13783_LED_CONTROL2,
78 MC13783_LED_CONTROL3,
79 MC13783_LED_CONTROL4,
80 MC13783_LED_CONTROL5,
81 MC13783_SPARE,
82 MC13783_TRIM0,
83 MC13783_TRIM1,
84 MC13783_TEST0,
85 MC13783_TEST1,
86 MC13783_TEST2,
87 MC13783_TEST3,
88 MC13783_NUM_REGS,
89};
90
91void mc13783_init(void);
92void mc13783_set(unsigned address, uint32_t bits);
93void mc13783_clear(unsigned address, uint32_t bits);
94int mc13783_write(unsigned address, uint32_t data);
95int mc13783_write_multiple(unsigned start, const uint32_t *buffer, int count);
96uint32_t mc13783_read(unsigned address);
97int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count);
98
99#endif /* _MC13783_H_ */
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 8ee553e121..f86a188d05 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -81,6 +81,9 @@ void kernel_init(void)
81 memset(&all_queues, 0, sizeof(all_queues)); 81 memset(&all_queues, 0, sizeof(all_queues));
82 corelock_init(&all_queues.cl); 82 corelock_init(&all_queues.cl);
83 tick_start(1000/HZ); 83 tick_start(1000/HZ);
84#ifdef KDEV_INIT
85 kernel_device_init();
86#endif
84 } 87 }
85} 88}
86 89
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
index fc9abdb0e9..051b1c8479 100644
--- a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
@@ -23,7 +23,7 @@
23#include "backlight.h" 23#include "backlight.h"
24#include "lcd.h" 24#include "lcd.h"
25#include "power.h" 25#include "power.h"
26#include "spi-imx31.h" 26#include "mc13783.h"
27#include "debug.h" 27#include "debug.h"
28 28
29bool _backlight_init(void) 29bool _backlight_init(void)
@@ -33,14 +33,14 @@ bool _backlight_init(void)
33 33
34void _backlight_on(void) 34void _backlight_on(void)
35{ 35{
36 // This relies on the SPI interface being initialised already 36 /* LEDEN=1 */
37 spi_send(51, 1); 37 mc13783_set(MC13783_LED_CONTROL0, (1 << 0));
38} 38}
39 39
40void _backlight_off(void) 40void _backlight_off(void)
41{ 41{
42 // This relies on the SPI interface being initialised already 42 /* LEDEN=0 */
43 spi_send(51, 0); 43 mc13783_clear(MC13783_LED_CONTROL0, (1 << 0));
44} 44}
45 45
46/* Assumes that the backlight has been initialized */ 46/* Assumes that the backlight has been initialized */
diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c
new file mode 100644
index 0000000000..a01fab07d0
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c
@@ -0,0 +1,45 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 Michael Sevakis
11 *
12 * Clock control functions for IMX31 processor
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "system.h"
22#include "cpu.h"
23#include "clkctl-imx31.h"
24
25void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg,
26 enum IMX31_CG_MODES mode)
27{
28 volatile unsigned long *reg;
29 unsigned long mask;
30 int shift;
31 int oldlevel;
32
33 if (cg >= CG_NUM_CLOCKS)
34 return;
35
36 reg = &CLKCTL_CGR0 + cg / 16; /* Select CGR0, CGR1, CGR2 */
37 shift = 2*(cg % 16); /* Get field shift */
38 mask = CG_MASK << shift; /* Select field */
39
40 oldlevel = disable_interrupt_save(IRQ_FIQ_STATUS);
41
42 *reg = (*reg & ~mask) | ((mode << shift) & mask);
43
44 restore_interrupt(oldlevel);
45}
diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h
new file mode 100644
index 0000000000..da15ef2706
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h
@@ -0,0 +1,86 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 Michael Sevakis
11 *
12 * Clock control functions for IMX31 processor
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _CLKCTL_IMX31_H_
22#define _CLKCTL_IMX31_H_
23
24enum IMX31_CG_LIST
25{
26 /* CGR0 */
27 CG_SD_MMC1 = 0,
28 CG_SD_MMC2,
29 CG_GPT,
30 CG_EPIT1,
31 CG_EPIT2,
32 CG_IIM,
33 CG_ATA,
34 CG_SDMA,
35 CG_CSPI3,
36 CG_RNG,
37 CG_UART1,
38 CG_UART2,
39 CG_SSI1,
40 CG_I2C1,
41 CG_I2C2,
42 CG_I2C3,
43 /* CGR1 */
44 CG_HANTRO,
45 CG_MEMSTICK1,
46 CG_MEMSTICK2,
47 CG_CSI,
48 CG_RTC,
49 CG_WDOG,
50 CG_PWM,
51 CG_SIM,
52 CG_ECT,
53 CG_USBOTG,
54 CG_KPP,
55 CG_IPU,
56 CG_UART3,
57 CG_UART4,
58 CG_UART5,
59 CG_1_WIRE,
60 /* CGR2 */
61 CG_SSI2,
62 CG_CSPI1,
63 CG_CSPI2,
64 CG_GACC,
65 CG_EMI,
66 CG_RTIC,
67 CG_FIR,
68 CG_NUM_CLOCKS
69};
70
71enum IMX31_CG_MODES
72{
73 CGM_OFF = 0x0, /* Always off */
74 CGM_ON_RUN = 0x1, /* On in run mode, off in wait and doze */
75 CGM_ON_RUN_WAIT = 0x2, /* On in run and wait modes, off in doze */
76 CGM_ON_ALL = 0x3, /* Always on */
77};
78
79#define CG_MASK 0x3 /* bitmask */
80
81/* Enable or disable module clocks independently - module must _not_ be
82 * active! */
83void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg,
84 enum IMX31_CG_MODES mode);
85
86#endif /* _CLKCTL_IMX31_H_ */
diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
index aaa4bde0eb..f0f578b03e 100644
--- a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
@@ -19,6 +19,9 @@
19#include "config.h" 19#include "config.h"
20#include "system.h" 20#include "system.h"
21#include "avic-imx31.h" 21#include "avic-imx31.h"
22#include "spi-imx31.h"
23#include "mc13783.h"
24#include "clkctl-imx31.h"
22#include "kernel.h" 25#include "kernel.h"
23#include "thread.h" 26#include "thread.h"
24 27
@@ -42,10 +45,11 @@ static __attribute__((interrupt("IRQ"))) void EPIT1_HANDLER(void)
42 45
43void tick_start(unsigned int interval_in_ms) 46void tick_start(unsigned int interval_in_ms)
44{ 47{
45 CLKCTL_CGR0 |= CGR0_EPIT1(CG_ON_ALL); /* EPIT1 module clock ON - 48 imx31_clkctl_module_clock_gating(CG_EPIT1, CGM_ON_ALL); /* EPIT1 module
46 before writing regs! */ 49 clock ON - before writing
50 regs! */
47 EPITCR1 &= ~(EPITCR_OCIEN | EPITCR_EN); /* Disable the counter */ 51 EPITCR1 &= ~(EPITCR_OCIEN | EPITCR_EN); /* Disable the counter */
48 CLKCTL_WIMR0 &= ~(1 << 23); /* Clear wakeup mask */ 52 CLKCTL_WIMR0 &= ~WIM_IPI_INT_EPIT1; /* Clear wakeup mask */
49 53
50 /* mcu_main_clk = 528MHz = 27MHz * 2 * ((9 + 7/9) / 1) 54 /* mcu_main_clk = 528MHz = 27MHz * 2 * ((9 + 7/9) / 1)
51 * CLKSRC = ipg_clk = 528MHz / 4 / 2 = 66MHz, 55 * CLKSRC = ipg_clk = 528MHz / 4 / 2 = 66MHz,
@@ -66,11 +70,18 @@ void tick_start(unsigned int interval_in_ms)
66 EPITCR1 |= EPITCR_EN; /* Enable the counter */ 70 EPITCR1 |= EPITCR_EN; /* Enable the counter */
67} 71}
68 72
73void kernel_device_init(void)
74{
75 spi_init();
76 mc13783_init();
77}
78
69#ifdef BOOTLOADER 79#ifdef BOOTLOADER
70void tick_stop(void) 80void tick_stop(void)
71{ 81{
72 avic_disable_int(EPIT1); /* Disable insterrupt */ 82 avic_disable_int(EPIT1); /* Disable insterrupt */
73 EPITCR1 &= ~(EPITCR_OCIEN | EPITCR_EN); /* Disable counter */ 83 EPITCR1 &= ~(EPITCR_OCIEN | EPITCR_EN); /* Disable counter */
74 CLKCTL_CGR0 &= ~CGR0_EPIT1(CG_MASK); /* EPIT1 module clock OFF */ 84 EPITSR1 = EPITSR_OCIF; /* Clear pending */
85 imx31_clkctl_module_clock_gating(CG_EPIT1, CGM_OFF); /* Turn off module clock */
75} 86}
76#endif 87#endif
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
new file mode 100644
index 0000000000..3af8f35f69
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
@@ -0,0 +1,173 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "cpu.h"
21#include "spi-imx31.h"
22#include "mc13783.h"
23#include "debug.h"
24#include "kernel.h"
25
26/* This is all based on communicating with the MC13783 PMU which is on
27 * CSPI2 with the chip select at 0. The LCD controller resides on
28 * CSPI3 cs1, but we have no idea how to communicate to it */
29static struct spi_node mc13783_spi =
30{
31 CSPI2_NUM, /* CSPI module 2 */
32 CSPI_CONREG_CHIP_SELECT_SS0 | /* Chip select 0 */
33 CSPI_CONREG_DRCTL_DONT_CARE | /* Don't care about CSPI_RDY */
34 CSPI_CONREG_DATA_RATE_DIV_4 | /* Clock = IPG_CLK/4 - 16.5MHz */
35 CSPI_BITCOUNT(32-1) | /* All 32 bits are to be transferred */
36 CSPI_CONREG_SSPOL | /* SS active high */
37 CSPI_CONREG_SSCTL | /* Negate SS between SPI bursts */
38 CSPI_CONREG_MODE, /* Master mode */
39 0, /* SPI clock - no wait states */
40};
41
42static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)];
43static const char *mc13783_thread_name = "pmic";
44static struct wakeup mc13783_wake;
45
46static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
47{
48 while (1)
49 {
50 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
51 }
52}
53
54static __attribute__((interrupt("IRQ"))) void mc13783_interrupt(void)
55{
56 wakeup_signal(&mc13783_wake);
57}
58
59void mc13783_init(void)
60{
61 /* Serial interface must have been initialized first! */
62 wakeup_init(&mc13783_wake);
63
64 /* Enable the PMIC SPI module */
65 spi_enable_module(&mc13783_spi);
66
67 create_thread(mc13783_interrupt_thread, mc13783_thread_stack,
68 sizeof(mc13783_thread_stack), 0, mc13783_thread_name
69 IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
70}
71
72void mc13783_set(unsigned address, uint32_t bits)
73{
74 spi_lock(&mc13783_spi);
75 uint32_t data = mc13783_read(address);
76 mc13783_write(address, data | bits);
77 spi_unlock(&mc13783_spi);
78}
79
80void mc13783_clear(unsigned address, uint32_t bits)
81{
82 spi_lock(&mc13783_spi);
83 uint32_t data = mc13783_read(address);
84 mc13783_write(address, data & ~bits);
85 spi_unlock(&mc13783_spi);
86}
87
88int mc13783_write(unsigned address, uint32_t data)
89{
90 struct spi_transfer xfer;
91 uint32_t packet;
92
93 if (address >= MC13783_NUM_REGS)
94 return -1;
95
96 packet = (1 << 31) | (address << 25) | (data & 0xffffff);
97 xfer.txbuf = &packet;
98 xfer.rxbuf = &packet;
99 xfer.count = 1;
100
101 if (!spi_transfer(&mc13783_spi, &xfer))
102 return -1;
103
104 return 1 - xfer.count;
105}
106
107int mc13783_write_multiple(unsigned start, const uint32_t *data, int count)
108{
109 int i;
110 struct spi_transfer xfer;
111 uint32_t packets[64];
112
113 if (start + count > MC13783_NUM_REGS)
114 return -1;
115
116 /* Prepare payload */
117 for (i = 0; i < count; i++, start++)
118 {
119 packets[i] = (1 << 31) | (start << 25) | (data[i] & 0xffffff);
120 }
121
122 xfer.txbuf = packets;
123 xfer.rxbuf = packets;
124 xfer.count = count;
125
126 if (!spi_transfer(&mc13783_spi, &xfer))
127 return -1;
128
129 return count - xfer.count;
130}
131
132uint32_t mc13783_read(unsigned address)
133{
134 uint32_t packet;
135 struct spi_transfer xfer;
136
137 if (address >= MC13783_NUM_REGS)
138 return (uint32_t)-1;
139
140 packet = address << 25;
141
142 xfer.txbuf = &packet;
143 xfer.rxbuf = &packet;
144 xfer.count = 1;
145
146 if (!spi_transfer(&mc13783_spi, &xfer))
147 return (uint32_t)-1;
148
149 return packet & 0xffffff;
150}
151
152int mc13783_read_multiple(unsigned start, uint32_t *buffer, int count)
153{
154 int i;
155 uint32_t packets[64];
156 struct spi_transfer xfer;
157
158 if (start + count > MC13783_NUM_REGS)
159 return -1;
160
161 xfer.txbuf = packets;
162 xfer.rxbuf = buffer;
163 xfer.count = count;
164
165 /* Prepare TX payload */
166 for (i = 0; i < count; i++, start++)
167 packets[i] = start << 25;
168
169 if (!spi_transfer(&mc13783_spi, &xfer))
170 return -1;
171
172 return count - xfer.count;
173}
diff --git a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
index 10ee3f44c0..bcbe85a76b 100644
--- a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
@@ -18,66 +18,325 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "cpu.h" 19#include "cpu.h"
20#include "spi-imx31.h" 20#include "spi-imx31.h"
21#include "avic-imx31.h"
22#include "clkctl-imx31.h"
21#include "debug.h" 23#include "debug.h"
22#include "kernel.h" 24#include "kernel.h"
23 25
24 /* This is all based on communicating with the MC13783 PMU which is on 26/* Forward interrupt handler declarations */
25 * CSPI2 with the chip select at 0. The LCD controller resides on 27#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
26 * CSPI3 cs1, but we have no idea how to communicate to it */ 28static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void);
27 29#endif
28void spi_init(void) { 30#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
29 CSPI_CONREG2 |= (2 << 20); // Burst will be triggered at SPI_RDY low 31static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void);
30 CSPI_CONREG2 |= (2 << 16); // Clock = IPG_CLK/16 - we want about 20mhz 32#endif
31 CSPI_CONREG2 |= (31 << 8); // All 32 bits are to be transferred 33#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
32 CSPI_CONREG2 |= (1 << 3); // Start burst on TXFIFO write. 34static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void);
33 CSPI_CONREG2 |= (1 << 1); // Master mode. 35#endif
34 CSPI_CONREG2 |= 1; // Enable CSPI2; 36
37/* State data associatated with each CSPI module */
38static struct spi_module_descriptor
39{
40 volatile unsigned long *base;
41 int enab;
42 struct spi_node *last;
43 enum IMX31_CG_LIST cg;
44 enum IMX31_INT_LIST ints;
45 int byte_size;
46 void (*handler)(void);
47 struct mutex m;
48 struct wakeup w;
49 struct spi_transfer *trans;
50 int rxcount;
51} spi_descs[SPI_NUM_CSPI] =
52/* Init non-zero members */
53{
54#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
55 {
56 .base = (unsigned long *)CSPI1_BASE_ADDR,
57 .cg = CG_CSPI1,
58 .ints = CSPI1,
59 .handler = CSPI1_HANDLER,
60 },
61#endif
62#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
63 {
64 .base = (unsigned long *)CSPI2_BASE_ADDR,
65 .cg = CG_CSPI2,
66 .ints = CSPI2,
67 .handler = CSPI2_HANDLER,
68 },
69#endif
70#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
71 {
72 .base = (unsigned long *)CSPI3_BASE_ADDR,
73 .cg = CG_CSPI3,
74 .ints = CSPI3,
75 .handler = CSPI3_HANDLER,
76 },
77#endif
78};
79
80/* Common code for interrupt handlers */
81static void spi_interrupt(enum spi_module_number spi)
82{
83 struct spi_module_descriptor *desc = &spi_descs[spi];
84 volatile unsigned long * const base = desc->base;
85 struct spi_transfer *trans = desc->trans;
86 int inc = desc->byte_size + 1;
87
88 if (desc->rxcount > 0)
89 {
90 /* Data received - empty out RXFIFO */
91 while ((base[CSPI_STATREG_I] & CSPI_STATREG_RR) != 0)
92 {
93 uint32_t word = base[CSPI_RXDATA_I];
94
95 switch (desc->byte_size & 3)
96 {
97 case 3:
98 *(unsigned char *)(trans->rxbuf + 3) = word >> 24;
99 case 2:
100 *(unsigned char *)(trans->rxbuf + 2) = word >> 16;
101 case 1:
102 *(unsigned char *)(trans->rxbuf + 1) = word >> 8;
103 case 0:
104 *(unsigned char *)(trans->rxbuf + 0) = word;
105 }
106
107 trans->rxbuf += inc;
108
109 if (--desc->rxcount < 4)
110 {
111 unsigned long intreg = base[CSPI_INTREG_I];
112
113 if (desc->rxcount <= 0)
114 {
115 /* No more to receive - stop RX interrupts */
116 intreg &= ~(CSPI_INTREG_RHEN | CSPI_INTREG_RREN);
117 base[CSPI_INTREG_I] = intreg;
118 break;
119 }
120 else if (!(intreg & CSPI_INTREG_RREN))
121 {
122 /* < 4 words expected - switch to RX ready */
123 intreg &= ~CSPI_INTREG_RHEN;
124 base[CSPI_INTREG_I] = intreg | CSPI_INTREG_RREN;
125 }
126 }
127 }
128 }
129
130 if (trans->count > 0)
131 {
132 /* Data to transmit - fill TXFIFO or write until exhausted */
133 while ((base[CSPI_STATREG_I] & CSPI_STATREG_TF) == 0)
134 {
135 uint32_t word = 0;
136
137 switch (desc->byte_size & 3)
138 {
139 case 3:
140 word = *(unsigned char *)(trans->txbuf + 3) << 24;
141 case 2:
142 word |= *(unsigned char *)(trans->txbuf + 2) << 16;
143 case 1:
144 word |= *(unsigned char *)(trans->txbuf + 1) << 8;
145 case 0:
146 word |= *(unsigned char *)(trans->txbuf + 0);
147 }
148
149 trans->txbuf += inc;
150
151 base[CSPI_TXDATA_I] = word;
152
153 if (--trans->count <= 0)
154 {
155 /* Out of data - stop TX interrupts */
156 base[CSPI_INTREG_I] &= ~CSPI_INTREG_THEN;
157 break;
158 }
159 }
160 }
161
162 /* If all interrupts have been remasked - we're done */
163 if (base[CSPI_INTREG_I] == 0)
164 {
165 base[CSPI_STATREG_I] = CSPI_STATREG_TC | CSPI_STATREG_BO;
166 wakeup_signal(&desc->w);
167 }
168}
169
170/* Interrupt handlers for each CSPI module */
171#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
172static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void)
173{
174 spi_interrupt(CSPI1_NUM);
175}
176#endif
177
178#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
179static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void)
180{
181 spi_interrupt(CSPI2_NUM);
182}
183#endif
184
185#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
186static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void)
187{
188 spi_interrupt(CSPI3_NUM);
189}
190#endif
191
192/* Write the context for the node and remember it to avoid unneeded reconfigure */
193static bool spi_set_context(struct spi_node *node,
194 struct spi_module_descriptor *desc)
195{
196 volatile unsigned long * const base = desc->base;
197
198 if ((base[CSPI_CONREG_I] & CSPI_CONREG_EN) == 0)
199 return false;
200
201 if (node != desc->last)
202 {
203 /* Switch the module's node */
204 desc->last = node;
205 desc->byte_size = (((node->conreg >> 8) & 0x1f) + 1 + 7) / 8 - 1;
206
207 /* Keep reserved and start bits cleared. Keep enabled bit. */
208 base[CSPI_CONREG_I] =
209 (node->conreg & ~(0xfcc8e000 | CSPI_CONREG_XCH | CSPI_CONREG_SMC))
210 | CSPI_CONREG_EN;
211 /* Set the wait-states */
212 base[CSPI_PERIODREG_I] = node->periodreg & 0xffff;
213 /* Clear out any spuriously-pending interrupts */
214 base[CSPI_STATREG_I] = CSPI_STATREG_TC | CSPI_STATREG_BO;
215 }
216
217 return true;
35} 218}
36 219
37static int spi_transfer(int address, long data, long* buffer, bool read) { 220/* Initialize each of the used SPI descriptors */
38 return -1; /* Disable for now - hangs - and we'll use interrupts */ 221void spi_init(void)
222{
223 int i;
39 224
40 unsigned long packet = 0; 225 for (i = 0; i < SPI_NUM_CSPI; i++)
41 if(!read) { 226 {
42 /* Set the appropriate bit in the packet to indicate a write */ 227 struct spi_module_descriptor * const desc = &spi_descs[i];
43 packet |= (1<<31); 228 mutex_init(&desc->m);
229 wakeup_init(&desc->w);
44 } 230 }
45 /* Set the address of the packet */ 231}
46 packet |= (address << 25); 232
47 233/* Get mutually-exclusive access to the node */
48 /* Ensure data only occupies 24 bits, then mash the data into the packet */ 234void spi_lock(struct spi_node *node)
49 data &= ~(DATAMASK); 235{
50 packet |= data; 236 mutex_lock(&spi_descs[node->num].m);
51 237}
52 /* Wait for some room in TXFIFO */ 238
53 while(CSPI_STATREG2 & (1<<2)); 239/* Release mutual exclusion */
54 240void spi_unlock(struct spi_node *node)
55 /* Send the packet */ 241{
56 CSPI_TXDATA2 = packet; 242 mutex_unlock(&spi_descs[node->num].m);
57 243}
58 /* Poll the XCH bit to wait for the end of the transfer, with 244
59 * a one second timeout */ 245/* Enable the specified module for the node */
60 int newtick = current_tick + HZ; 246void spi_enable_module(struct spi_node *node)
61 while((CSPI_CONREG2 & (1<<2)) && (current_tick < newtick)); 247{
62 248 struct spi_module_descriptor * const desc = &spi_descs[node->num];
63 if(newtick > current_tick) { 249
64 *buffer = CSPI_RXDATA2; 250 mutex_lock(&desc->m);
65 return 0; 251
66 } else { 252 if (++desc->enab == 1)
67 /* Indicate the fact that the transfer timed out */ 253 {
68 return -1; 254 /* First enable for this module */
255 volatile unsigned long * const base = desc->base;
256
257 /* Enable clock-gating register */
258 imx31_clkctl_module_clock_gating(desc->cg, CGM_ON_ALL);
259
260 /* Reset */
261 base[CSPI_CONREG_I] &= ~CSPI_CONREG_EN;
262 base[CSPI_CONREG_I] |= CSPI_CONREG_EN;
263 base[CSPI_INTREG_I] = 0;
264 base[CSPI_STATREG_I] = CSPI_STATREG_TC | CSPI_STATREG_BO;
265
266 /* Enable interrupt at controller level */
267 avic_enable_int(desc->ints, IRQ, 6, desc->handler);
69 } 268 }
269
270 mutex_unlock(&desc->m);
70} 271}
71 272
72void spi_send(int address, unsigned long data) { 273/* Disabled the specified module for the node */
73 long dummy; 274void spi_disable_module(struct spi_node *node)
74 if(spi_transfer(address, data, &dummy, false)) { 275{
75 DEBUGF("SPI Send timed out"); 276 struct spi_module_descriptor * const desc = &spi_descs[node->num];
277
278 mutex_lock(&desc->m);
279
280 if (desc->enab > 0 && --desc->enab == 0)
281 {
282 /* Last enable for this module */
283 volatile unsigned long * const base = desc->base;
284
285 /* Disable interrupt at controller level */
286 avic_disable_int(desc->ints);
287
288 /* Disable interface */
289 base[CSPI_CONREG_I] &= ~CSPI_CONREG_EN;
290
291 /* Disable interface clock */
292 imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF);
76 } 293 }
294
295 mutex_unlock(&desc->m);
77} 296}
78 297
79void spi_read(int address, unsigned long* buffer) { 298/* Send and/or receive data on the specified node */
80 if(spi_transfer(address, 0, buffer, true)) { 299int spi_transfer(struct spi_node *node, struct spi_transfer *trans)
81 DEBUGF("SPI read timed out"); 300{
301 struct spi_module_descriptor * const desc = &spi_descs[node->num];
302 int retval;
303
304 if (trans->count <= 0)
305 return true;
306
307 mutex_lock(&desc->m);
308
309 retval = spi_set_context(node, desc);
310
311 if (retval)
312 {
313 volatile unsigned long * const base = desc->base;
314 unsigned long intreg;
315
316 desc->trans = trans;
317 desc->rxcount = trans->count;
318
319 /* Enable needed interrupts - FIFOs will start filling */
320 intreg = CSPI_INTREG_THEN;
321
322 intreg |= (trans->count < 4) ?
323 CSPI_INTREG_RREN : /* Must grab data on every word */
324 CSPI_INTREG_RHEN; /* Enough data to wait for half-full */
325
326 base[CSPI_INTREG_I] = intreg;
327
328 /* Start transfer */
329 base[CSPI_CONREG_I] |= CSPI_CONREG_XCH;
330
331 if (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED)
332 {
333 base[CSPI_INTREG_I] = 0;
334 base[CSPI_CONREG_I] &= ~CSPI_CONREG_XCH;
335 retval = false;
336 }
82 } 337 }
338
339 mutex_unlock(&desc->m);
340
341 return retval;
83} 342}
diff --git a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
index 5f6cfc984f..c17a272aaa 100644
--- a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
@@ -16,8 +16,58 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#define DATAMASK 0xFF000000 19#ifndef _SPI_IMX31_H_
20#define _SPI_IMX31_H_
20 21
22#define USE_CSPI1_MODULE (1 << 0)
23#define USE_CSPI2_MODULE (1 << 1)
24#define USE_CSPI3_MODULE (1 << 2)
25
26/* SPI_MODULE_MASK is set in target's config */
27enum spi_module_number
28{
29#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
30 CSPI1_NUM = 0,
31#endif
32#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
33 CSPI2_NUM,
34#endif
35#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
36 CSPI3_NUM,
37#endif
38 SPI_NUM_CSPI,
39};
40
41struct spi_node
42{
43 enum spi_module_number num; /* Module number (CSPIx_NUM) */
44 unsigned long conreg; /* CSPI conreg setup */
45 unsigned long periodreg; /* CSPI periodreg setup */
46};
47
48struct spi_transfer
49{
50 const void *txbuf;
51 void *rxbuf;
52 int count;
53};
54
55/* One-time init of SPI driver */
21void spi_init(void); 56void spi_init(void);
22void spi_send(int address, unsigned long data); 57
23void spi_read(int address, unsigned long* buffer); 58/* Enable the specified module for the node */
59void spi_enable_module(struct spi_node *node);
60
61/* Disabled the specified module for the node */
62void spi_disable_module(struct spi_node *node);
63
64/* Lock module mutex */
65void spi_lock(struct spi_node *node);
66
67/* Unlock module mutex */
68void spi_unlock(struct spi_node *node);
69
70/* Send and/or receive data on the specified node */
71int spi_transfer(struct spi_node *node, struct spi_transfer *trans);
72
73#endif /* _SPI_IMX31_H_ */
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h
index 327d72b7bc..8db0c78eb7 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/system-target.h
@@ -35,6 +35,9 @@ static inline void udelay(unsigned int usecs)
35 35
36void system_prepare_fw_start(void); 36void system_prepare_fw_start(void);
37void tick_stop(void); 37void tick_stop(void);
38void kernel_device_init(void);
39
40#define KDEV_INIT
38 41
39#define HAVE_INVALIDATE_ICACHE 42#define HAVE_INVALIDATE_ICACHE
40static inline void invalidate_icache(void) 43static inline void invalidate_icache(void)